R6RS Macros and R6RS librariesを今度こそ移植する の5
R6RS recordsはちょっと理解しづらい。。
多重defineのつかいみち
西の横綱(rnrs records syntactic)のテストが通るようになった。
LarcenyのERR5RS recordsによる実装を移植していて、その移植の過程でかなり大幅に間違っていたのが原因となっていた。
今回の移植ではexpand-libraryを使うとプログラムをすぐ展開できるので、それを見るのが早い。
oku@sandbox ~/repos/mosh/ext/newruntime $ cat work.scm (import (rnrs)) (define-record-type test-RECORD (fields (immutable FIELD))) oku@sandbox ~/repos/mosh/ext/newruntime $ gosh expand-library.scm work.scm work.exp oku@sandbox ~/repos/mosh/ext/newruntime $ cat work.exp (begin (ex:import-libraries-for-run '(((rnrs) 0)) '(&build~1261007528~3417) 0) (define &test-RECORD~1261008908~7 (make-record-type-descriptor 'test-RECORD #f #f #f #f '#((immutable FIELD)))) (define &%%RECORD-SYNTAX-IGNORED~1261008908~9 (&preferred-cd-set!~1261007528~1628 &test-RECORD~1261008908~7 (make-record-constructor-descriptor &test-RECORD~1261008908~7 #f #f))) (define &make-test-RECORD~1261008908~11 (record-constructor (&preferred-cd~1261007528~1627 &test-RECORD~1261008908~7))) (define &test-RECORD?~1261008908~13 (record-predicate &test-RECORD~1261008908~7)) (define &test-RECORD-FIELD~1261008908~15 (record-accessor &test-RECORD~1261008908~7 0)))
(展開後のソースは読みやすくなるように編集した...)
このとき、Larcenyの実装では :
- 副作用のある式をdefine列の中で使うために、無視されるシンボル(%%RECORD-SYNTAX-IGNORED、元はignoredだが目立たないので替えた)を決めてそこにdefineする形としている。これは多重defineを禁止した元のmoshでは再現出来ない。
- 今回は多重defineそのものを許可している。
- Larcenyは、そもそもdefineをset!に変換してしまうのであまり大きな問題ではない。
- 上手いトリックを使えばこれは回避できる可能性も有るが、コンパイラ側が扱えない可能性も有るので保留中。
- gensymしてdefineする手もあるが...
- Larcenyの実装では、R6RSの要求を満たすために、record-type == record-type-descriptorとなるようにしている。
- record-constructorは、別途ハッシュテーブルを内部で生成し、そこを参照するようにしている。
例外の移植
昨日のコミットでは、例外ハンドラが例外を表すrtdを参照しようとしてさらに例外を起こすことで例外の無限ループが起きていた。これは、例外を表すrtdをエクスポートすることで解決した。
今のところ例外は展開されないので、例外が起きても具体的な問題はわからない。
oku@sandbox ~/repos/mosh $ ./mosh (CMD: ()) nmosh top program nmosh> (import (NON-EXISTANT)) (LOOKING-UP... (NON-EXISTANT)) Exception: error in raise: unhandled exception has occurred #<compound-condition #<record &assertion> #<record &who> #<record &message> #<record &irritants>>
例外の正確な処理はまだ移植していない。特にr6rs-test-suiteのexceptionテストは常に問題が起こる。
当初は、例外は全てScheme側で実装してしまうつもりだったが、同時にportのようなC++で実装されている部分もScheme側に移植する必要があるので何とも言えない。なんとかmosh側の例外機構を活用したいが。。