2015年5月3日日曜日

[コンピュータ開発][コンピュータシステムの理論と実践]OCamlでHack assemblerを実装

「コンピュータシステムの理論と実装」
第6章 アセンブラ まで進んだ。

第一段階のシンボルフリーなHackアセンブラをOCamlで実装した。
https://github.com/takeisa/ocaml-hack-assembler

  • 依存ライブラリはCoreとRe2。
  • コマンドラインの解析は、Coreのライブラリを使用。ここを参考に実装した。

実行例

デバッグ用出力がいろいろ出ているが、Add.asmをアセンブルして、Add.hackを出力している。

$ ./assembler Add.asm && echo "----" && cat Add.hack 
ignore :   1 43 [// This file is part of www.nand2tetris.org]
ignore :   2 51 [// and the book "The Elements of Computing Systems"]
ignore :   3 36 [// by Nisan and Schocken, MIT Press.]
ignore :   4 37 [// File name: projects/06/add/Add.asm]
ignore :   5  0 []
ignore :   6 22 [// Computes R0 = 2 + 3]
ignore :   7  0 []
command:   8  2 [@2]
command:   9  3 [D=A]
dest=2 comp=48 jump=0
command:  10  2 [@3]
command:  11  5 [D=D+A]
dest=2 comp=2 jump=0
command:  12  2 [@0]
command:  13  3 [M=D]
dest=1 comp=12 jump=0
----
0000000000000010
1110110000010000
0000000000000011
1110000010010000
0000000000000000
1110001100001000

その他

デバッグ用に、レコード型やバリアント型の値を文字列に変換して表示したかったので、以前、Twitterで教えていただいたmeta_convを使って、変換する関数を自動で生成させようとした。
とりあえず、以下の単純なコードを作成して、

==hello.ml==
open Meta_conv.Open
open Ocaml_conv

type hello =
  | Foo of string
  | Bar of int
with conv(ocaml)

ocamlfindでコンパイルすると、エラーとなった。

$ ocamlfind ocamlc -verbose -package meta_conv,ocaml_conv -syntax camlp4o -package meta_conv.syntax hello.ml 
findlib: [WARNING] Interface topdirs.cmi occurs in several directories: /home/satoshi/.opam/4.02.1/lib/ocaml, /home/satoshi/.opam/4.02.1/lib/ocaml/compiler-libs
Effective set of preprocessor predicates: preprocessor,syntax,camlp4o
Effective set of compiler predicates: pkg_meta_conv,pkg_compiler-libs,pkg_compiler-libs.common,pkg_ocaml_conv,pkg_camlp4,pkg_type_conv,pkg_meta_conv.syntax,syntax,autolink,byte
+ ocamlc.opt -verbose -I /home/satoshi/.opam/4.02.1/lib/ocaml/compiler-libs -I /home/satoshi/.opam/4.02.1/lib/ocaml_conv -I /home/satoshi/.opam/4.02.1/lib/ocaml/camlp4 -I /home/satoshi/.opam/4.02.1/lib/type_conv -I /home/satoshi/.opam/4.02.1/lib/meta_conv -pp "camlp4 '-I' '/home/satoshi/.opam/4.02.1/lib/ocaml/camlp4' '-I' '/home/satoshi/.opam/4.02.1/lib/type_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-parser' 'o' '-parser' 'op' '-printer' 'p' 'pa_type_conv.cma' 'meta_conv.cmo' 'pa_meta_conv.cma' " hello.ml
+ camlp4 '-I' '/home/satoshi/.opam/4.02.1/lib/ocaml/camlp4' '-I' '/home/satoshi/.opam/4.02.1/lib/type_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-I' '/home/satoshi/.opam/4.02.1/lib/meta_conv' '-parser' 'o' '-parser' 'op' '-printer' 'p' 'pa_type_conv.cma' 'meta_conv.cmo' 'pa_meta_conv.cma'  'hello.ml' > /tmp/ocamlpp86694c
File "hello.ml", line 1:
Error: Error while linking hello.cmo:
Reference to undefined global `Ocaml_conv'
ocamlc.opt returned with exit code 2 


Ocaml_convがうまく参照できないようだ。
きっとライブラリの指定の方法か、OCamlの開発環境に原因があるのだろう。
こちらは、そのうち調べてみよう。