ふつパイラ
私の住むマンションは、エントランスの所に郵便受けがあり、毎日確認に行くのが私の日課に なっている。
入っているのは、近くで売り出したマンションの広告や建売の広告ばかり。あるマンションなんて 施主が倒産したので、後を引き継いだ工務店が投売りしてた。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部にあると思っています。心してもう一度、読み直そう。