Syntax highlighter

2011-06-30

思案中のこと

Sagittariusが遅い。
結構まともなライブラリを作ろうとしているのだが、それのテストというか1回走らせるのに2~3秒、長いときで5秒以上待たされる。ライブラリを除いた実際のコードは数行なのにだ。
これは、まぁ、原因まで全部分かっていて、コアの機能以外は全部そのときに読み込んで、コンパイル、実行しているからだ。さらに、マクロ展開の関係もあって、コンパイラがかなり重い。

っで、FASLを導入してみようかと思ったのだが、これって単にS式をバイナリにしただけなのね。それでは結局上記のルーチンが走るので美味しくない。どうやら本当に必要なのはCompiled Cacheのようだ。

名前などどうでもよくて、それが要ると思って考えていたのだが、いろいろ解決しなければならない問題が既にある。

・ライブラリ単位にするか、ファイル単位にするか。

どちらも問題があるが、ライブラリ単位がすっきりしてると思うのでそっちで。

・複数ライブラリが1ファイルにある場合はどうするか?
・ライブラリ外でモジュールを読み込んでからライブラリを作成しているファイル(実際既にある)ものはどうするか?
・どの段階でキャッシュするか?
・実行ファイル内(この場合は起動ファイルを指す)で、ライブラリを定義した場合にそれをキャッシュするか?

思いついたというか、考えている段階で答えが浮かばなかったのがこの辺。
4つ目は最悪キャッシュしてしまえばいいか。っで、import時に引っ掛けると。ただ、キャッシュ時間が問題になりそうだ。

さて、どうしようかな。

日本人がオランダに長くいすぎてしまったと感じるとき

これの逆版
あんまり思いつくこともないんだけど、面白そうだから。

1.電車やバスが10分以上遅れてもなんとも思わない。
日常的に10分くらい遅れる。というか時刻表はたんなる目安でしかない。

2.自転車が歩道を走ってると警察を呼びたくなる。
自転車用の道があるんです。

3.シリコン製のへらを日常的につかう。
けちなオランダ人は、洗う必要がなくらいきれいにビンの中身を食べます。

4.大麻のにおいが嗅ぎ分けれるようになった。
一応、コーヒーショップの外では吸ってはいけないはずなんだけど。

5.休暇が1週間だと短いと感じるようになった。
まとめて取れるんです。

6.残業する人を見ると可哀想だなぁと思うようになった。
まぁ、滅多に見ないけど。

7.自分は背が低い方だと思うようになった。
成人男性の平均身長185cmだったかな?

ネタが尽きた。
7個とは微妙すぎる数字だ。
なんかあったらまた書こう。

単に行き詰っていたので息抜きに書いてみたとも言う。

2011-06-28

発見し難いバグ

原因を特定しにくいと言うべきか。
まぁそんなバグに悩まされている。Javaや元々GCがあるような言語なら問題ないのだが、(ここまで言ったら何の問題かすぐ分かるが)、メモリー管理の問題である。

現状SagittariusではBoehmGCを使っている(そのうち取り替えてやる!と思っているが、GCはむずい。。。)。別にGCが悪いというわけではなく、どこかでメモリー破壊が行われている可能性があるとう問題。
読み込んだシンボルが、ある特定のプロセスを踏むと変更されている。発現性は100%なのだが、場所の特定ができない。この前、正規表現を実装している時に同じ現象が起きた。そのときは割り当てたメモリを越えて値を埋めていたので起きたのだが、その際の原因は非常に簡単で、メモリのサイズの計算が行われていなかったというもの。
例えば、mallocでintの配列10個確保するのにこう書いてたという問題:(int)malloc(10)
JavaやC++やってるとnew演算子が便利すぎて忘れる問題の一つだと信じている。信じたいとも言う。っが、今回はどうも違うらしい。メモリ割り当ての箇所を全部チェックしたが問題ない。ということは、割り当て時の不具合ではなく、使用時の不具合なので、それが使用されている箇所を全部洗いなおす必要がある。正直、砂漠の砂を数える気分になる(そんなにはないが)

どこかにいいメモリ破壊検出ツールはないだろうか?

2011-06-26

(match)ライブラリで見つかった気になるバグ

Sagittarius Schemeは一応Andrew Wrightのパターンマッチが使えるのだが、それを使用したプログラムで起きた気になるバグの話。

現在Sagittarius SchemeではCとSchemeを繋ぐ仕組みとして.stubファイルを使用している。ちなみに、アイデアはGaucheからいただきました。っで、そのファイルをcgenというSchemeで書かれたプログラムに処理させてCのファイルを生成する。利点はわずらわしい引数の数のチェックとか、型チェックとかをそれなりに省略できることと、Schemeのマクロチックにマクロを記述でき、かつそれらが確実にインライン展開されること。実際、.stubファイルから生成された.cファイルはサイズが4倍程度に膨らむ。つまり記述量が4分の1ですむということ。
話がそれた。そのプログラムでは上記のmatchを使っているのだが、最近変更したsyntax-rulesをsyntax-caseで実装するというので問題が起きた。matchの中で'_が単なるシンボルとして比較されていたのだが、syntax-rulesで生成された後のS式は全部ラップされて識別子になっている。っで、'_の比較が失敗するというもの。
何が気になるかというと、これからもしmatch相当の何かを書くことがあった場合、この辺を気にしないといけないということと、他のR6RSの実装ならその辺を気にしなくてもいいということ。正直、他の処理系との移植性は大分あきらめた部分はあるのでどうでもいいのだが、'_とか'...が識別子にラップされてもいいのかなぁとちょっと不安になってたりする。
現状動いているものを変更するのは怖いので(単に面倒くさがり)、とりあえず現状のまま様子をみて、問題が発生したら変えるということにしよう。

P.S.
Twitterをはじめました。アカウント名は@tk_ripleです。こういうところでさらしていいものなのかもわからないのですが、どうせ見てる人も少ないということで。

P.S.2
最初に登録したユーザー名から上記に変更してます。こんなものも変更できるのね、Twitter。

2011-06-25

めがね

前の眼鏡を5年以上使っていたので、新しいのを買った。
Tommy Hilfigerというブランド物である。まさか自分がブランドの着いたものを買うとは夢にも思わなかった。

つけた自分を鏡で見たときに、なんともトレンドな感じがして違和感を覚えたが、まぁいいか。

以下は余談。
こっちでは視力の指標に+-数字というのを使う。
例えば僕の視力は-6(左)と-8(右)という結果だった(ちなみに、マイナスは近視でプラスは遠視)。今まで日本の0.1とかと違って自分がどれくらい目が悪いのか分かり難い。
慣れの問題ではあるのだが、単位が変わるというのはいつでもそれに対応するのに困る。

2011-06-18

ぐぬぬ

syntax-rulesが遅いのでsyntax-caseで実装したものを試してみたら、動かない。いや、動くんだけど、正しく動かない。
その理由も分かったのだが、解決できる気がしない・・・

理由は分かれば単純なのだが、例えばこんなの。
;; testはR6RSテストスイートのマクロ
(test (let ((x 'outer))
   (let-syntax ((m (syntax-rules () ((m) x))))
     (let ((x 'inner))
       (m))))
 'outer)
これは割りと典型的な例で、マクロの中でマクロを生成すると起きる。(実は違うかもしれない)
この例だと(m)が返す値はouterじゃないとまずいのだけど、innerの方を返す。何故か?
syntax-caseがパターンとテンプレートをコンパイルする際にすべてのシンボルを識別子へと変換する。その際に、すべてのxが同一の識別子に変換されるので、let-syntax内にあるxとinnerそ束縛しているxが同一のものになってしまう。
これを回避するうまい方法が思いつかない。マクロの展開フェーズとコンパイルのフェーズが分かれていれば、マクロを展開する際に使用する環境やらマクロ展開フェーズやらがいろいろ知っていればいいのだが、現状の実装ではletが変数を束縛するということを知っているのはletに束縛された構文オブジェクトだけなんだよね。
また、マクロを展開してからコンパイルするわけではないので、マクロ展開中に変数束縛を作るマクロが出現した際に結局おかしくなる。
こうなってくると僕の足りない脳みそでが悲鳴を上げてくる。
現在の実装はYpsilonのものをSagittariusでも動くように適当にいじったものだが、根本的な理解をしていなかったため結構穴がある(例えば上記のものとか)。
この穴をふさぐためには実装のしなおしだろうか?しかし、そもそも今のモデルで上記のような問題を解決できるのだろうか?

・・・

考えるか・・・

2011-06-16

Socketが動いた!!

Socketの実装が完了。まだテストケース書いてないけど・・・

とりあえず簡単なechoサーバーを書いてみた。
(import (sagittarius socket))

;; creates echo server socket with port number 5000
(define echo-server-socket (make-server-socket "5000"))

;; addr is client socket
(let loop ((addr (socket-accept echo-server-socket)))
  (call-with-socket
   addr
   (lambda (sock)
     ;; socket-port creates binary input/output port
     ;; make it transcoded port for convenience.
     (let ((p (transcoded-port (socket-port sock)
          ;; on Sagittarius Scheme native-transcoder
          ;; uses utf8 codec for ASCII compatibility.
          ;; For socket programming it might be better
          ;; to specify eol-style with crlf.
          ;; But this sample just shows how it goes.
          (native-transcoder))))
       (call-with-port
 p
 (lambda (p)
   (put-string p "please type something\n\r")
   (put-string p "> ")
   ;; gets line from client.
   (let lp2 ((r (get-line p)))
     (unless (eof-object? r)
       (print "received: " r)
       ;; just returns message from client.
       ;; NB: If client type nothing, it'll throw assertion-violation.
       (put-string p r)
       (put-string p "\r\n> ")
       ;; waits for next input.
       (lp2 (get-line p)))))))))
  ;; echo server waits next connection.
  (loop (socket-accept echo-server-socket)))
これを起動しておいて、別ターミナルからtelnet localhost 5000で繋ぐと動く動く!!
あんまりにうれしいので、example/socket/echo.scmとか作ってしまった。初example!!

次はFFIでその次がGUIか。
GUIまでできたら実用的なアプリを書きたいなぁ。

2011-06-14

宗教観

<<警告>>
以下の文章は繊細な問題をダイナミックに否定しています。中東辺り発祥の宗教に属している方は読まないことをお勧めします。もし気分を害したり、聖戦だぁ!なんて言い出されても当方は一切責任を取りません。

身近な人がユダヤ教に改宗しようとしているのの関係で、元々宗教、特に中東辺りを発祥とするものが嫌いだったのに拍車がかかった。
とりあえず、前々から思っていたこととして、唯一神教は総じて腐っているということ。
何故か?こいつらの過激派は自分たちの神のためといって戦争を起こす。また、他宗教の人間を邪教徒といい虐殺する権利を持っていると言い放つ。実際、現在問題になっているテロリストの多くはイスラム教だし、歴史を紐解けばキリスト教が起こした略奪戦争は多々ある。
また、神父、宣教師、その他いろいろは神の言葉と称して人の洗脳を行う。その昔日本でも宣教師が神の教えと称し、奴隷として人々の売り買いをしたことは割と有名だと思う。そのため秀吉はキリスト教を全面的に禁止したとかしないとか(多分理由の一つだろう)

正直中身の教えに関してはどうでもいいのだが、とりあえずユダヤ教についていろいろ知ってしまった。まぁ、そのために嫌いになったという話もあるのだが。
とりあえず、ユダヤ教の好きになれない食べ物の話。
彼らにはKosher(日本語訳は知らない)というルールがあって、割と厳しく食べていいものとだめなもの、混ぜて食べてはいけないものがある。中でも一番気に入らないのは、Kosherな肉というやつだ。
正直何が普通の肉と違うのかはさっぱり分からないが、彼らの話によると、宗教上他の生き物の苦しみを体内に取り込んではいけないため、できる限り苦しまないよう殺した肉のみを食べるという。この段階で傲慢さがにじみ出てるなぁと個人的には思うのだが、まだまだある。豚は不浄な生き物なので食べない。魚はいいけど、海老とかは海の昆虫なので食べない。Unkosherなものを作った鍋は使ってはだめ、だってその鍋には苦しみが染み付いてるじゃん。
ちなみに、彼らによるとKosherでない肉はBAD MEAT(訳は適当に自分でどうぞ)なんだそうだ。つまり、我々が食べている肉は中に苦しみが詰まっていて、食べるには不浄な物なんだと。(そこまでは言ってないかも--;)
個人的にKosherとか単なる言い訳にしか聞こえなくて、「肉食べたいけど、教えに背くなぁ・・・よしそれっぽい規定作って食べれるようにしよう」という風にしか見えない。素直に菜食主義になれと言ってやりたい。(というかもう言ったが)

つらつら書き出すと止まらなくなりそうなのでこの辺で。
でも、何よりも一番怖いなぁと思ったのは、宗教は人を変えるということ。大抵の場合は悪い方に。人と話す際の3大タブーに、政治、人種、宗教があるが、まさにそうだなと実感した。彼らは自分たちの宗教に関する否定的な意見は聞きたくない。まぁ、そこまでは分かるが、問題だなぁと思ったのは、こちらが疑問に感じたことを質問しても攻撃的な態度だと多くの場合は捕らえる。何故か?理由はおそらくいたって簡単で、「自分が何の疑問も無く信じていることに対して疑問を投げかけるなど、その宗教があたかも信仰するに値しないごみくずのように扱われているかの様に感じる」のだろう。そこにもはや言論の自由はない。
っが、困ったことに宗教人というのは多かれ少なかれ自分の信仰しているものを他人と共有したがる傾向がある。そうすると事は複雑になって、相手はこちらからは肯定的な意見しか聞きたくないが、こっちはそんなもの聞きたくないので否定的もしくは懐疑的な反応しかでない。こちらが大人の対応を見せて聞き流す、もしくは肯定的に適当な相槌を打つということをすればいいのだが、そうした際にこちらにもその宗教に対して興味があるなんて思われたくないし、肯定的な理解をしているとさえも思われたくない。この辺は個人的に譲れない部分になるので、関係が悪化しようが、瓦解しようがおそらく反応は変わらない。

これを読んで、本当にそんなことあるのかよ!と思った方、多少の脚色はあるけど上記の意見は体験に基づくものだったいりするのです。
もし周りに、なんらかの宗教に改宗しようなんて考えている知人がいる方、その人と良好な関係を保ちたいなら全力で止めることをお勧めします。

2011-06-12

マルチスレッド

とりあえずなんとなく形になってきた。
Windowsでも動くようにしたら後はバグ取りなんだろうけど、どこにバグがあるのかさっぱり分からない。マルチスレッドは難しいなぁ。正直、デッドロックが発生した際にそれがC側なのかScheme側なのか判別が難しい。今になって必要だったかなぁ?と少し疑問も。。。

それはさておき、現状で少し(大分?)問題が露呈してきた。
まず、遅い!!
通常の状態ならそこまで遅くないのだが、(rnrs)ライブラリのimportが遅い。理由は分かっていて、(rnrs)ライブラリをimportすると40近いファイルをロード&コンパイルする。これはそもそもr6rsのスタンダードライブラリが20以上に分かれていて、Sagittariusの実装ではそれぞれがファイルになっている。っで、さらにその中に実装の記述が入っていて、初回ロードでコンパイルと実行がなされるので遅い。
この辺、MoshとYpsilonでは(rnrs)ライブラリを組み込みにしていて、少なくともコンパイルの処理がカットされているのでそこまでの負荷にはなっていない。加えて、Sagittariusではsyntax-rulesが重たい処理なのでR6RSが要求するcase-lambdaなどsyntax-rulesで記述されているマクロのコンパイル及び、展開が非常に重い。これはsyntax-rulesをsyntax-caseで書けば早くなるのだが、何故かexportが上手くいっていないのでとりあえず保留にしてある。
次いで、エラー処理。
with-exception-handlerやguardマクロを使って何かを記述した際に、C側(VM含む)で何らかの例外を投げると、例外処理がされずに終了することがある。これも理由は分かっていて、Schemeで記述されたassertion-violationをC側で呼び出さないと落ちる。理由は分かっているのだが、最終的に同じ関数を呼び出すのになぜこれが起きるのかいまいち理解してない。とりあえず、VMと、CとSchemeを繋ぐ部分のエラー処理でassertion-violationを使用することで回避。
まだいくつかあるけど、大きなのでREPLがない。
REPLを実装すること自体はそんなに難しくないんだけど(履歴なし、変な入力を受け付けないものならSchemeで実装されたものがあったりする)、そのままでは使い辛すぎてもう少し何とかしないと、と思いつつ他の方にいってて進まない。どうしようかな。

落ちはない。

2011-06-02

iPhoneのiOSをバージョンアップ

してる最中。
やってる途中でいろいろ問題が発生して焦ったがなんとかなりそう。
写真とか残ってるといいなぁ・・・

とりあえず起きた問題。
  • iTunesのアップデートでCドライブの空き容量がなくなった。
    • .Net Frameworkをアンインストール
    • Open Officeをアンインストール
    • 復元ポイントの削除
    • WINDOWSフォルダ内の$NTinstallフォルダを削除
      • 600MB -> 2.3GBまで増えた
  • エラー番号1604が発生
    • Appleのサイトに詳しいトラブルシューティングがあったので実行
今のところ同期作業が進行中で何とかなったくさい。あとはJBするだけか。SBSettingsがないと不便すぎるのよw

2011-06-01

Verion 0.1.0

とりあえずそんなバージョンでリリース。
単にこれから加える変更は0.1.0以降と決めていただけで、当初の目的であるR6RS準拠というところまで実は行っていない。自分用のアプリが書ければいいや、という風に思っているのでそこまで気にしなくてもいいだろうというのもあるが。
なんかの格言に、「どうにも行かなくなったらそれをバージョン1と呼べ」なんてのがあったけど(コンピュータージョークだったかな?)、そんな感じ。

とりあえず、0.1.0から0.2.0の間でやりたいなぁと思っていることとその優先順位。
  1. マルチスレッド
  2. ソケット
  3. FFI
  4. GUI
そこそこ実用的なことを書こうと思ったらこれくらいはいりそう。1.はsrfi-21準拠にする予定。srfi-21はsrfi-18の後継みたいなので。でも、Larcenyとかsrfi-18, 21はPOSIXを前提にしてるからサポートしないという姿勢もとってるし、変えるかもしんない。
ソケットは、YpsilonとMoshのAPIが一緒だった気がするので、それに合わせる予定。何があるか列挙しないと。
FFIはYpsilonから盗む。正直自分の頭で考えられるようなものじゃないくせに、あると非常に便利なので。あと、dlopen相当のものが必要になってくるはずなので、その辺も考える。
GUIは設計から考えないといけないんだよね。JavaのSwingみたいにしようかと思ったけど、あれってオブジェクト指向じゃないと厳しい気がする。ActionListenerとか。Qtのシグナルみたいな感じにするといいかな?

優先順位は上から高→低なんだけどどれも全部ほしいので頑張る。ただ、ソケットとマルチスレッドは実装の順番を入れ替えるかもしれない。
まずは、こういった足すことを前提にしたCから使えるユーザーオブジェクトの作成からかな。Schemeからは実は近いのがあるんだけど(いろいろおかしなことになってきてるけど、ばっちり使われてる)、Cからそれを使うのは結構厳しい。なのでCから使われることを前提にしたものがいる。構想はあるのでとりあえずやってみる感じ。ただ、同時実装に近いものになるだろうので、第一号はソケットかスレッドのどちらかになる。難易度の低そうな方とも言う。

上記ができたら、DBIとかの実装もできるだろうか?
仕事で使うツールとして今の玩具の状態を早く脱したい。

2011-05-31

BBCニュースより

iPhoneでBBCニュースを読んでいたときに見つけた記事。
Japan pensioners volunteer to tackle nuclear crisis

(リンクが切れてても知りません)

僕のiPhoneにはBBCとNew York Timesのアプリがあるのだが、BBCの方が記事が短くていい感じなのでよく使ってる。
(あと、割と文章が平易なので読みやすいというのもあるが)
っで、今日上記の記事を見つけた。
訳を載せていいのか分からないので、要約だけ。
定年を迎えた元原発作業員の方が、同年代の同僚、友人に声をかけて自分たちが福島原発での作業を行うように働きかけている。論理的に60歳を越えたら放射能による癌が発現しにくいため(発現するまでに13~15年かかるので、それまでに寿命がくるという意味で)、若者よりもリスクが低い。だが、決して「神風特攻隊」ではなく、「生きて返ってくる」という意志の元で行う。
大体こんな感じ?(要約苦手な上に、日本語が出てこなくなってる・・・)

こういう方が戦後の日本を支えたのかなぁと思う一方、余生を満喫してほしいなぁとも思ったり。

2011-05-30

syntax-rulesの挙動がおかしい件

の原因が分かった。
分かってしまえば非常に単純かつ根が深い問題である。
原因は、quoteをした際に識別子がunwrapされてしまうため、環境の参照の際に見つからなくなるというもの。
なので、quoteが現れたときにunwrapしなければこの問題はおきない。

なんだけど、syntax-rulesないでquoteしたシンボルをwriteもしくはdisplayを使って出力した際に、S式ではなく識別子が出力されてしまう。
多分これを回避するためにunwrapしたんだと思うけど、それではまずいよなぁ。
どうしたものか。

2011-05-29

ドイツに行ってきた

この帽子ドイツんだ?オランダ!
ということでドイツに行ってきた。

といっても、ベルリンとか遠いところではなく、オランダとの国境から比較的ちかいところ。
その辺にMovie Parkなるものがあるといことで行ってきた。
どんなのかなぁと思っていってみたら、Universal Studioのドイツ版でした。サイズは日本のより少し小さいくらいか?でもローラーコースターもあったので、その気になれば比較的遊べると思う。
と思うと書いたのは、僕は無理だったので・・・いや、すべてのアトラクションがドイツ語だし。大学の時に第2外国語でとったけど、きれいさっぱり忘れたし。Ich bin ein Berliner Bal だけではねぇ・・・

そんなこんなであまり遊べず、帰りの電車の関係もありデュッセルドルフに移動。ここにはラーメン屋があるという噂を聞いたので食べれたらいいなぁ、くらいの感覚で来たのだが、これまたびっくり、一つのとおりが日本人街になってた!!
あと、なにかのイベントがあるのか、アニメキャラクターのコスプレイヤーが一杯。よくネットで海外のコスプレはレベルが高いというのを見るのだが、ありゃPhotoshopの技術が高いのか、1割くらいの当たりの写真を使ってるかのどちらかだと思う。
実際、9割くらいはGood looking boy/girlではなかったので(叶姉妹風。古い?)
目的のラーメン屋も意外とあっさり見つかり、辺りからは日本語の会話が山ほど聞こえるなか、ラーメンを注文。普通か旨い部類に入ると思うけど、あんまりラーメン通ではないのでよく分からん。
でも、醤油ラーメン、タンタン麺、餃子+飲み物2つで29.20ユーロは高くね?

//////
投稿を分けるのも面倒なので、こっちに。

ドイツに、というときはデュッセルドルフに行ったときに感じたこと。
海外で日本人に会うとどうも変な気分になる。理由はよく分からなかったんだけど、ラーメン食べてるときになんとなく分かった気がした。
彼らも英語(もしくはドイツ語)を話す。なんとなく自分だけではないんだなぁというのを突きつけられるのと同時に何故か劣等感を感じてるんだろう。多分その劣等感は、彼らはまだ若い。僕が彼らくらいの時にはそんなことできなかった、そんな勇気もなかったというのが劣等感につながっているのだろう。
おそらく、個人的にあまり日本人コミュニティーに近づかないのは、それも理由の一つなのだろう。いや、でもアムスの日本人コミュニティーは駐在さんメインだよなぁ。それとこれは別か?郷に入って郷に従わないのが嫌いなだけかも。

//////
超個人的な話。

弱音を吐きそうになる瞬間が増えてきた。原因も分かっていて、自分ではどうしようもできない問題の部類の一つだ。これが仕事とか、言語とか、文化の違いとかならまだ楽だったんだけどなぁ。
じっとこらえるべきか、日本に帰ることを視野に入れるべきか。後者はきっと今と同じくらいに苦しいのも分かってたりするんだよねぇ。
去年応募したアメリカのグリーンカード当たらないかなぁ。(アメリカ嫌いなのにこんなことを願うあたり、かなりキテるなぁ)

2011-05-26

マクロに潜んでいる罠

たいした物言いだがたいしたことではない。
Sagittariusで発見して、Gaucheでも再現するという不思議なバグの話。
以下のコード
(define-syntax hoge
  (syntax-rules ()
    ((_ args ...)
     (letrec-syntax 
  ((find (syntax-rules ()
    ((_ a b c)
     (next a b))))
   (next (syntax-rules ()
    ((_ a b c)
     (find a b c))
    ((_ a b)
     (print a b)))))
       (find args ...)))))
(hoge 1 2 3)
findとかnextはSSAXのマクロから取っているだけで別に名前はなんでもいい。
これを実行すると、unknown variable nextというのが出る。でも、letrec-syntaxの部分だけ取り出して実行すると動く。
原因は分かっていて、識別子の比較が弱いためにコンパイル時環境のlookupが失敗しているのだ。
不思議なこととしては、最初のhogeが展開されたときに作成される識別子は正しく作成されている(この場合は同じアドレスという意味)のに、lookup時はなぜか失敗する。
コンパイル時環境のlookupはGaucheとほぼ同じなのだが、syntax-rulesの実装はまるで違う(はず)。なのに両方でこれが発生するということは、まぁ、そこなんだろう。もしくは、syntax-rules内で予定外の識別子がrenameされたかのどちらかなんだけど。

原因を追究していたのだが、疲れたので息抜きに書いてみた。

2011-05-25

昨日の続き

とりあえず、途中経過をダンプしてみた結果、どうもSagittariusのsyntax-rulesにおけるキーワードの扱いが間違っていそうである。

どういうことか?
昨日の段階で、arg-nameが複数回出現していると書いたが、よく見るとsyntax-rulesでキーワードを設定する箇所でばっちり全部吐き出している。つまり、展開されたarg-nameはすべてキーワードなのだ。
ということは、これはR5RSだろうがR6RSだろうがきっちり通るはずなのだが、Gaucheでは通らなかったので勘違いしてしまったということである。

マクロのパターン展開をもう一回見直すことに相成り候。。。

2011-05-24

sxmlを使えるようにしたい

仕事柄、自分用の何かしらを書くのにXMLパーサーくらいは絶対的に必要になる。ということでSchemeでつかえるXMLパーサーということでSSAXをporting中。
必要そうなSRFI(13、14とか)を実装して、いざSSAXを流してみたらsyntax-rulesでおかしなエラーを出してくる。
エラーはパターン変数が重複しているというもの。
Ypsilonで試したらきっちり動く。でも、Gaucheでは同じエラー。
ちなみに、こんなsyntax-rules
(define-syntax ssax:define-labeled-arg-macro
  (syntax-rules ()
    ((ssax:define-labeled-arg-macro
       labeled-arg-macro-name
       (positional-macro-name
  (arg-name . arg-def) ...))
      (define-syntax labeled-arg-macro-name
 (syntax-rules ()
   ((labeled-arg-macro-name . kw-val-pairs)
     (letrec-syntax
       ((find 
   (syntax-rules (arg-name ...)
                   ;; ここが問題
     ((find k-args (arg-name . default) arg-name
        val . others)    ; found arg-name among kw-val-pairs
      (next val . k-args)) ...
     ((find k-args key arg-no-match-name val . others)
       (find k-args key . others))
     ((find k-args (arg-name default)) ; default must be here
       (next default . k-args)) ...
     ))
  (next   ; pack the continuation to find
    (syntax-rules ()
      ((next val vals key . keys)
        (find ((val . vals) . keys) key . kw-val-pairs))
      ((next val vals) ; processed all arg-descriptors
        (rev-apply (val) vals))))
  (rev-apply
    (syntax-rules ()
      ((rev-apply form (x . xs))
        (rev-apply (x . form) xs))
      ((rev-apply form ()) form))))
       (next positional-macro-name () 
  (arg-name . arg-def) ...))))))))
問題なのはarg-nameが2回出現していること。仮に展開されるとしてもarg-nameは同じものを指すので、展開後もパターン変数が重複する。仕様書を完全に理解してないけど、これはsyntax-rulesの動作として正しい。個人的に気になるのは、Ypsilonではなぜ動いたのかということと、他のR6RSの実装でもこれは動くのかということ。(もし他のR6RSの実装でも動くのなら、ちと考えないといけないかもしれない)
っで、sxmlをライブラリとして持っているGaucheはなぜ動いたのかというところを探ってみたところ、単純にバージョンが古かった。最新版といっても2004年ととても古いのだが、Gaucheのはさらに1年古い2003年のもので、make-parserはdefine-macroで書かれていた。
一応最新版と思われるbiglooで動く実装を覗いたら、そちらもdefine-mecroで実装してある。う~ん、define-macro自体はあるし、er-macro-transformerでの書き換えも非常に楽なんだけど、どうしたものだろう?
とりあえず他のも見てみるか。

2011-05-20

VCでのコンパイルが通った

__imp_の魔の手に苦しんだが、一応コンパイルが通った。
ってか、__impl_って同考えてもVCの不具合にしか思えないくらいひどい仕様だ。これを使って開発しようという気をごっそりともってく、かなり高等な武器だともいえるか。
R6RSのテストも既知のものを除いて通らないものは1つだけという優秀さであった。
通らなかったのは、UTF16のトランスコーダーが返すEOLでcrlfが期待値なのにlfを返してるというもの。
あんまりまじめに見てないが、まぁ、割と簡単に直るだろう。
そろそろバージョン0.1.0のリリースも近いか?

2011-05-19

かなりいいところまで来た感じ

RacketのR6RSテストのほぼすべてが通るようになった。
とりあえず通らないテストとしては、bound-identifier=?のテストの1つと、contribのテスト1つ。contribのテストは多分syntax-rulesがsyntax-caseのサブセットじゃないと通らないんじゃないかなぁと推測。
Sagittariusではsyntax-rulesはexplicit renamingで実装されているのでまぁいいかと。
bound-identifier=?のはそこまで厳密にrenamingが行われていないのと、まだまだsyntax-caseの実装が怪しいのとで原因不明。そのうち直ったらいいなぁとは思うが、この手続き自体あまり使わないので放置になるかな。
もう一つ、別環境でやったら通らなかったテストが、ポート周りのテストでstring->bytevectorとbytevector->stringを使ってるやつ。ファイルを介してテストを行うので、改行コードが処理系内部の改行コードとして処理されて通らない。ファイルを介さなければ普通にでる。気が向いたときに直そう。

ちょいちょい気になるのが、多分どこかでメモリ破壊を起こしてるんだろうなぁという出力結果が出るときがあるのだが、どこだ分からない上に、デバッガ使うと辿れない系のやつ。
見つけ次第つぶしてるけど果てしない。

ここからは愚痴。
ついでにVCでもコンパイルしようとVisual Studio 2010をインストール。っが、VCってC99に対応してないのね。結構手直しが必要になってる。特にmath.hのINFINITYとNANが面倒。あと、off_tのサイズが違うのでどうしようかな。off_t使ってるとこを全部int64_tにした方がいいだろうか?

2011-05-08

(再)letrec-syntaxにはまる

実際にはlet-syntaxだが、どちらも同じなので。
あんまりR6RSの仕様書をまじめに読んでないことが分かってしまうのだが、こんなコードにはまる。
;; (1)
(let () 
  (let-syntax ((def (syntax-rules ()
        ((def stuff ...) (define stuff ...)))))
    (def foo 42))
  foo)
;; (2)
(let-syntax ((def (syntax-rules ()
      ((def stuff ...) (define stuff ...)))))
  (def foo 42))
foo
R5RSでは上記のコードは不正になる。let(rec)-syntaxはおそらくスコープを作るのだろう。(Gaucheで確認しただけで、R5RSを読んだわけではない)
っが、R6RSではこれはOKで、let(rec)-syntaxはbeginと同じなのだそうだ。なので、(1)の場合は単なるinternal defineに展開されると考えればいいのだろう。
explicit phasingでlet-syntaxが展開された後のことを考えればそうなのかもしれないが、(2)のケースを考えると納得がいかないなぁ。

どちらにしろ、これは直さないと。でも、とりあえず先送りにしよう。こんな書き方することはないだろうし。