ふつパイラ
私の住むマンションは、エントランスの所に郵便受けがあり、毎日確認に行くのが私の日課に なっている。
入っているのは、近くで売り出したマンションの広告や建売の広告ばかり。あるマンションなんて 施主が倒産したので、後を引き継いだ工務店が投売りしてた。2100 -> 1800でどうでっしゃろ? とか、モデルルームの家具や設備一式をおまけで付けますとか、、 よっぽど売れてないんだねえ。
でも、そんな広告が毎日入ってるとなると、いいかげんにうざい。郵便受けの所に、ごみ箱を 設置しておいて、そんなスパムは即ごみ箱行きにしたいぞ。
そういうスパムをより分けて、届くのは宅配業者が持ってくる、通販の分厚いカタログ。今は 秋冬モードのオンパレードだ。勿論、届け先は女房名。おいらの所に来るのは、月1の請求書 ばかりだなあ。こういうのは、情報格差と言うんだろうか?
emacsでHaskell入力の補間
Emacs での Haskell プログラミングを幸せにするが 公開された。今まで有りそうで無かったものだ。scheme等では同等なツールが既にあるのに haskellに無かったと言う事は、単純に考えると人口の差だな。
まずは、FreeBSDでやってみる。haskell-src-extsが古いと文句を言われた。こういう時は、 cabal update してから、cabal upgrade haskell-src-exts したよ。
次はWindowsに入れようとしたんだけど、下準備が大変だった。こちらは、 haskell-src-exts が入ってないってば、と言われた。
そなら、cabal update してから、cabal install haskell-src-exts すればいいんだな。 やってみたら、今度は、happy が無いからやだ、と言われた。
ほなら、cabal install happy だなと、やり始めたら、インストールするには perlが要りまっせ と、あるまじき事を言い出したよ。なんたる事だ。
気が進まなかったけど、perl を突っ込んでから、happy -> haskell-src-exts -> ghc-mod と 辿って、やっと入った。もう少し、cabalさんには利口になって貰わねば。こういう面倒さが Haskell人口が増えない原因の一旦になってるのね。
あの方に、haskell少人口対策大臣になって欲しいぞ。
所で、今回の根っ子になった、happy って何物よ? たまたま、読んでいた ふつうのコンパイラをつくろうの、P45に 解説が出ていた。happyはLALR(1)、ParsecはLL(k)を扱えるパーサーだそうです。
ふつパイラで遊ぶ
RHG読書会で ふつパイラの読書会が行われている。もう17章まで進んでしまったと言う事は、残りは第4部の リンクとライブラリー編だけの数章か。ならば、今から出席しても(次回は、10/17)遅いか。
そもそも、この本を手に取って、第3章から終わりまで一気読みし、暫くほってあって、最近 頭から読み始めると言う変則な事をしてたからなあ。少し、自習してみっか。
と、言う事で、久しぶりにlenny/debianをひっぱり出してきた。だって、Linux必須なんだ もん。後は、javac,ant,javaccとか、豪快な環境を要求される。(cbcを*.javaから作る場合)
何事もソースからやってみない事には、気が済まない私ですから、READMEに従って
sakae@debian:~/cbc-1.0$ ls ChangeLog README bin/ build.xml install.sh* net/ tools/ Makefile ToDo build.properties import/ lib/ test/ unit/ sakae@debian:~/cbc-1.0$ make make: `default' に対して行うべき事はありません.
しょうがないので、Makefileを覗いてみた結果
sakae@debian:~/cbc-1.0$ rm lib/cbc.jar lib/libcbc.a
sakae@debian:~/cbc-1.0$ make
ant compile
Buildfile: build.xml
init:
parser:
[javacc] Java Compiler Compiler Version 4.1d1 (Parser Generator)
[javacc] (type "javacc" with no arguments for help)
[javacc] Reading from file /home/sakae/cbc-1.0/net/loveruby/cflat/parser/Parser.jj . . .
[javacc] Note: UNICODE_INPUT option is specified. Please make sure you create the parser/lexer using a Reader with the correct character encoding.
[javacc] File "TokenMgrError.java" does not exist. Will create one.
[javacc] File "ParseException.java" does not exist. Will create one.
[javacc] File "Token.java" does not exist. Will create one.
[javacc] File "SimpleCharStream.java" does not exist. Will create one.
[javacc] Parser generated successfully.
compile:
[mkdir] Created dir: /home/sakae/cbc-1.0/build
[mkdir] Created dir: /home/sakae/cbc-1.0/build/classes
[javac] Compiling 193 source files to /home/sakae/cbc-1.0/build/classes
[jar] Building jar: /home/sakae/cbc-1.0/lib/cbc.jar
BUILD SUCCESSFUL
Total time: 27 seconds
cd lib; make libcbc.a
make[1]: ディレクトリ `/home/sakae/cbc-1.0/lib' に入ります
ar crs libcbc.a stdarg.o alloca.o
make[1]: ディレクトリ `/home/sakae/cbc-1.0/lib' から出ます
次は、試験してみっか。
sakae@debian:~/cbc-1.0$ make test cd test; make test make[1]: ディレクトリ `/home/sakae/cbc-1.0/test' に入ります ./run.sh 01_exec........ 02_print................................................................ : 36_alloca.................................................. 37_setjmp................ PASS (1920 tests) -- debian / Linux 2.6.26-2-686 i686 make[1]: ディレクトリ `/home/sakae/cbc-1.0/test' から出ます
インストールしたら、試運転。
sakae@debian:~/tmp$ cat hoge.cb
import stdio;
int main(int argc, char **argv){
printf("Hello CBC\n");
}
sakae@debian:~/tmp$ cbc hoge.cb
sakae@debian:~/tmp$ ./hoge
Hello CBC
ああ、青木さんの血と汗を一瞬のうちに堪能しちゃった。と、思ったらおまけが有ったよ。
sakae@debian:~/tmp$ cat hoge.s
.file "hoge.cb"
.section .rodata
.LC0:
.string "Hello CBC\n"
.text
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
movl $.LC0, %eax
pushl %eax
call printf
addl $4, %esp
.L0:
movl %ebp, %esp
popl %ebp
ret
.size main,.-main
gas って、opcode src,dest と並んでるんだよね。この並びの方が私の趣味に合うなあ。 また、movlと言う具合に、lだとかw,bと言うのが付くのもm68kアセンブラみたいで好感が 持てる。AT&T風記述万歳。ああ、$が頭に付くと即値というのもいいねぇと、徹底的に intel風味を嫌うのでした。
次は、AST。
sakae@debian:~/tmp$ cbc --dump-ast hoge.cb
<<AST>> (hoge.cb:2)
variables:
functions:
<<DefinedFunction>> (hoge.cb:4)
name: "main"
isPrivate: false
params:
parameters:
<<Parameter>> (hoge.cb:4)
name: "argc"
typeNode: int
<<Parameter>> (hoge.cb:4)
name: "argv"
typeNode: char**
body:
<<BlockNode>> (hoge.cb:4)
variables:
stmts:
<<ExprStmtNode>> (hoge.cb:5)
expr:
<<FuncallNode>> (hoge.cb:5)
expr:
<<VariableNode>> (hoge.cb:5)
name: "printf"
args:
<<StringLiteralNode>> (hoge.cb:5)
value: "Hello CBC\n"
schemeは、ここまでは人間がやるんだな。
sakae@debian:~/tmp$ cbc --dump-ir hoge.cb
<<IR>> (hoge.cb:2)
variables:
functions:
<<DefinedFunction>> (hoge.cb:4)
name: main
isPrivate: false
type: int(int, char**)
body:
<<ExprStmt>> (hoge.cb:5)
expr:
<<Call>>
type: INT32
expr:
<<Addr>>
type: INT32
entity: printf
args:
<<Str>>
type: INT32
entry: net.loveruby.cflat.entity.ConstantEntry@f5da06
そして、ASTを扱いやすいように中間言語に変換したぞ。
sakae@debian:~/tmp$ cbc --print-asm -fverbose-asm hoge.cb
.file "hoge.cb"
.section .rodata
.LC0:
.string "Hello CBC\n"
.text
.globl main
.type main,@function
main:
# ---- Stack Frame Layout -----------
# (%ebp): return address
# 4(%ebp): saved %ebp
# 8(%ebp): argc
# 12(%ebp): argv
# -----------------------------------
pushl %ebp
movl %esp, %ebp
# line 5: printf("Hello CBC\n");
# Call {
# Str {
movl $.LC0, %eax
# }
pushl %eax
call printf
addl $4, %esp
# }
.L0:
movl %ebp, %esp
popl %ebp
ret
.size main,.-main
そして、これは、高橋会長ご推薦図書「計算機プログラミングの基礎概念」風の、まぜこぜ スタイルによる出力。さりげなく、こういうのを用意してるとは、さすが青木さん! と、cbcは、いろいろな段階の 結果が見られるから、勉強になるなあ。どんな段階があるかは
sakae@debian:~/tmp$ cbc --help
Usage: cbc [options] file...
Global Options:
--check-syntax Checks syntax and quit.
--dump-tokens Dumps tokens and quit.
--dump-ast Dumps AST and quit.
--dump-semantic Dumps AST after semantic checks and quit.
--dump-ir Dumps IR and quit.
--dump-asm Dumps AssemblyCode and quit.
--print-asm Prints assembly code and quit.
:
最後に、javaccがどんな*javaを吐き出したか確認しておく。
sakae@debian:~/cbc-1.0/net/loveruby/cflat/parser$ ls -ltr 合計 220 -rw-r--r-- 1 sakae sakae 2314 2009-05-10 23:52 LibraryLoader.java -rw-r--r-- 1 sakae sakae 31109 2009-05-24 19:23 Parser.jj -rw-r--r-- 1 sakae sakae 42175 2009-10-05 13:47 ParserTokenManager.java -rw-r--r-- 1 sakae sakae 101151 2009-10-05 13:47 Parser.java -rw-r--r-- 1 sakae sakae 4493 2009-10-05 13:47 TokenMgrError.java -rw-r--r-- 1 sakae sakae 3833 2009-10-05 13:47 Token.java -rw-r--r-- 1 sakae sakae 12093 2009-10-05 13:47 SimpleCharStream.java -rw-r--r-- 1 sakae sakae 3789 2009-10-05 13:47 ParserConstants.java -rw-r--r-- 1 sakae sakae 6683 2009-10-05 13:47 ParseException.java
ChangeLogによると、このプロジェクトは、"Tue Mar 20 22:09:22 2007 Minero Aoki"から 始められたようです。一人でコンパイラーを作るなんて、とんでもなく大変な事。 そして、そのコード解説を本にしちゃうなんて、常人には出来る事ではありません。 この本の真価は、3,(特に)4部にあると思っています。心してもう一度、読み直そう。