Gauche:Bugs:log10
- Linux/AMD64のdouble->half
- string-upcase!/downcase! が引数を要求する? (0.8.10)
- (hash-table-put! (make-hash-table 'string=?) () 1) でsegmentation fault(0.8.10)
- gensymで生成したシンボルとstring->symbolで生成したシンボルが一致しない (0.8.10)
- open-input-uvectorに渡したベクタがGCされない (0.8.10)
- inline展開されるbuiltin関数のbindを後から変更したときの動作
- Segmentation fault
- identity が undocumented (0.8.10 and CVS HEAD)
- エンディアンを変えたときにwrite-blockが余計なデータを出力する(0.8.10)
- http-getやhttp-postがキーワード引数 sink と flusher を無視する(CVS HEAD)
- condでsegmentation fault (0.8.10)
- ext/netでmake testが止まります
- CVS HEAD(2007/05/17 03:01:27 PDT)で2fails
- Gauche 0.8.10 のリファレンス 10.10.2「時間に関する問い合わせ」の用語について
- Linux/AMD64のsockaddr-addr
- BrainFuckでコアダンプ(CVS HEAD)
- rfc.ftp の call-with-ftp-connection (CVS HEAD)
- Bignumと#i1/0の比較がエラーになる (0.8.10)
- mapが多値を返す (0.8.10)
- 拡張ライブラリのコンパイルでwarningが出る (0.8.10)
- sys-realpathが使えない (0.8.10)
- force-output の 定義 (0.8.10)
- プロファイラを使うとポートがGCされない (0.8.10)
- ext/net/net.c の typo (0.8.10)
Linux/AMD64のdouble->half
Rui (2007/05/14 20:35:58 PDT): Lingrに書いた件。Linux/AMD64でsrc/test-arith.cの次のテストに失敗するようです。
test_half("double->half, rounding", 0x3ffe, Scm_DoubleToHalf(1.99853515625)); /* m=#b1111111110.10 */
testing double->half, rounding, expects 3ffe =>ERROR: got 3fff
備前さんの話だとNetBSD/amd64では次のエラーがでるとのこと。エラーになるテストが違います。
testing double->half, rounding, expects 3fff =>ERROR: got 3ffe
- Shiro(2007/08/06 03:19:57 PDT): むむむ。
VMWare上の Ubuntu x86_64 (CPUはAthlon)だと再現しません。
Cコード上のリテラルの読み込み時の丸めモードの差かなともちょっと思ったんですが
該当の10進リテラルは誤差無く2進に変換できる数なのでそれも妙です。
もしできれば、src/number.cのScm_DoubleToHalf()中の:
/*ここと*/ if (m%2 == 1) { if (r == 0) { /* half point. we round to even */ if (m&2) m += 2; } else { m += 2; } } /*ここと*/ /* drop rounding bits */ m >>= 1; if (m >= 0x800) { e += 1; m >>= 1; } if (e == 0 && m >= 0x400) { e += 1; m &= ~0x400; } /*ここ*/
のmの値を16進でダンプするようにして、failするケースでのダンプ結果を もらえませんか。
- び(2007/08/06 20:45:06 PDT): NetBSD/amd64で検証してみました。石はIntel Xeon 3060です。
--- number.c 17 Jul 2007 03:24:49 -0000 1.148 +++ number.c 7 Aug 2007 03:50:16 -0000 @@ -38,6 +38,7 @@ #include <string.h> #include <ctype.h> #include <float.h> +#include <stdio.h> #define LIBGAUCHE_BODY #include "gauche.h" #include "gauche/bignum.h" @@ -346,6 +347,7 @@ #endif /*SIZEOF_LONG < 8*/ m += 1<<(mbits+1); /* recover hidden bit */ + fprintf(stderr, "DUMP#1: v = %lf, m = %lx\n", v, m); if (m%2 == 1) { if (r == 0) { /* half point. we round to even */ @@ -356,6 +358,7 @@ } /* drop rounding bits */ + fprintf(stderr, "DUMP#2: v = %lf, m = %lx\n", v, m); m >>= 1; if (m >= 0x800) { e += 1; @@ -368,6 +371,7 @@ if (e >= 31) { /* overflow by rounding */ return dd.components.sign? 0xfc00 : 0x7c00; } + fprintf(stderr, "DUMP#3: v = %lf, m = %lx\n", v, m); /* at this point, normalized numbers should get 0x400 <= m <= 0x7ff, e > 0, and denormalized numbers should get 0 <= m <= 0x3ff, e == 0. So we don't need to treat denormalized
このパッチを当てて、src/test-arith を実行した抜粋です。: DUMP#1: v = 1.998779, m = ffd DUMP#2: v = 1.998779, m = ffd DUMP#3: v = 1.998779, m = 7fe testing double->half, rounding, expects 3fff =>ERROR: got 3ffe :
他は全てokでした。ちなみに実機はKahuaプロジェクトのサーバなので、shiroさんなら直接試してもらえます。
- Rui(2007/08/07 00:27:17 PDT): 原因はScm_DoubleToHalfの中でintでシフトしているからじゃないでしょうか。手元ではこれで直りました。だとするとshiroさんのところで再現しない原因が謎ですが。
--- src/number.c 17 Jul 2007 03:24:49 -0000 1.148 +++ src/number.c 7 Aug 2007 07:23:24 -0000 @@ -339,10 +339,10 @@ all 0 or not. */ #if SIZEOF_LONG >= 8 m = dd.components.mant >> (52-mbits-1); - r = dd.components.mant & ((1 << (52-mbits-1)) - 1); + r = dd.components.mant & ((1UL << (52-mbits-1)) - 1); #else /*SIZEOF_LONG < 8*/ m = dd.components.mant0 >> (20-mbits-1); - r = (dd.components.mant0 & ((1 << (20-mbits-1)) - 1))|dd.components.mant1; + r = (dd.components.mant0 & ((1UL << (20-mbits-1)) - 1))|dd.components.mant1; #endif /*SIZEOF_LONG < 8*/ m += 1<<(mbits+1); /* recover hidden bit */
- Shiro(2007/08/07 01:24:56 PDT): おーそれだ。NetBSD/AMD64もそれで通りました。 うちで再現しないと言ったのは実は単に見落としてただけでした。 最近テスト最後の1行サマリを確認して済ませる癖がついちゃってて…
string-upcase!/downcase! が引数を要求する? (0.8.10)
srfi-13 で (string-downcase! str) とするとエラーになります。
gosh> (use srfi-13) #<undef> gosh> (define s (list->string (string->list "HELLO"))) ;; mutable string のつもり s gosh> s "HELLO" gosh> (string-downcase s) ;; これは期待通り。(副作用なし) "hello" gosh> s "HELLO" gosh> (string-downcase! s) ;; ここが期待とは違う。(副作用あり!) *** ERROR: real number required: #<undef> Stack Trace: _______________________________________ gosh> (string-downcase! s 0 1) ;; start と end を与えると動く。 "hELLO" gosh> s "hELLO" gosh> (string-downcase! s 0) ;; start=0 だと動かないんだけど、 *** ERROR: real number required: #<undef> Stack Trace: _______________________________________ gosh> (string-downcase! s 1) ;; start=1 だと動く。 "hello" gosh> s "hello"
Gauche 0.8.8 までは動いていたんですけど, Gauche 0.8.10 にバージョンアップしたら動かなくなってしまいました。yuki (2007/07/31 06:54:23 PDT)
- Shiro: あ、エンバグしてました。
--- libsrc/srfi-13.scm 2 Mar 2007 07:39:12 -0000 1.6 +++ libsrc/srfi-13.scm 31 Jul 2007 18:44:54 -0000 @@ -597,7 +597,7 @@ (define (%string-*case! converter) (lambda (s . args) - (let-optionals* args ((start 0) end) + (let-optionals* args ((start 0) (end (string-length s))) (if (and (= start 0) (= end (string-length s))) (%string-replace-body! s (converter s)) (string-copy! s start (converter s start end))))))
ただ、他のScheme用に書かれたライブラリを流用しているなら仕方ありませんが、 Gauche用に書いたものなら、string-downcase! などの文字列変更系の関数を 使う意味は全く無いです。一度string-downcaseなどの副作用無し版を適用して、 結果を入れ替える、という操作を行っているだけなので。- yuki: ありがとうございます。副作用ありの方が効率よいのかも……などと考えていたのですが、副作用なしの方を使うようにします。functional programming としても副作用ない方がきれいですしね。
(hash-table-put! (make-hash-table 'string=?) () 1) でsegmentation fault(0.8.10)
'string=?を比較関数としたハッシュテーブルに、キー()で値を入れると、セグメンテーション違反になりました。 環境は、Linux(Fedora core 3) i386 32bitです。
- Shiro(2007/07/26 00:18:41 PDT): stringかどうかのチェックはちゃんとやってたんですが、 stringでない場合にエラールーチンに渡すオブジェクトを間違ってました。 fixしました。
gensymで生成したシンボルとstring->symbolで生成したシンボルが一致しない (0.8.10)
koguro(2007/07/10 07:25:32 PDT): もしかしたら gensym の使い方が間違っているのかもしれませんが、以下のようなケースで一致すると思われるシンボルの比較が不一致となります。
gosh> (define a (gensym)) a gosh> a G1 gosh> (eq? a (string->symbol "G1")) #f
-2007/07/10 07:53:55 PDT: gensymはどのシンボルとも異なるシンボルを生成します。そのため、string->symbolで同じシンボルが生成されては意味がなくなりますし、できません。この例の場合はGaucheにおけるgensymで生成されたシンボルに対する外部表現が普通のシンボルのものと区別が付かないことが問題なのだと思います。(LISP/Schemeは少しかじっただけの初心者なので外してるかも知れません。どなたかフォローをお願いします)
- Shiro(2007/07/10 10:40:33 PDT): そのとおり。gensymは"internされない (テーブルに登録されない)" シンボルを生成します。したがってlegacyマクロで一時変数を生成するのにgensymを使えば、その変数は絶対に他と衝突しないことが保証されます。 ただ、それをprintしてしまうと名前だけではinternされているかとうかの区別はつきません。 Common Lispではinternされていないシンボルは #:a のように表示されるので ややわかりやすいです (それでも、#:a が2箇所出てきた場合にそれらが同一のもの であったかどうかは判別できません---それを読み込んだ場合には#:aは全て 別のものになります)。
- koguro(2007/07/11 05:43:05 PDT): なるほど、了解です。ただ、そうするとGaucheユーザリファレンスの6.5シンボルで「Gaucheでは、全てのシンボルはintern、すなわち内部のテーブルに登録されています。 そのため、同じ外部表記を持つシンボルは常にeq?です。」とあるのですが、ここの記述を修正した方がよいかなと思いました。
- Shiro(2007/08/09 19:05:17 PDT): マニュアルの記述修正しました。
open-input-uvectorに渡したベクタがGCされない (0.8.10)
shinya (2007/07/05 02:16:55 PDT):
gosh> (use gauche.uvector) #<undef> gosh> (use gauche.vport) #<undef> gosh> (define wv (make-weak-vector 2)) wv gosh> (define buf (make-u8vector 1)) buf gosh> (define in (open-input-uvector buf)) in gosh> (weak-vector-set! wv 0 buf) #<undef> gosh> (weak-vector-set! wv 1 in) #<undef> gosh> wv #,(<weak-vector> 2 #u8(0) #<buffered-input-port #f 00A284D0>) gosh> (set! buf #f) #f gosh> (set! in #f) #f gosh> (gc) #<undef> gosh> (gc) #<undef> gosh> wv #,(<weak-vector> 2 #u8(0) #f)
open-input-uvectorの替わりに下のtest1を使っても同様にGCされませんが、test2だとGCされるので、letrecがあやしいように思います。
(define (test1 uvector) (letrec ((filler (lambda (vec) (u8vector-length uvector)))) (make <buffered-input-port> :fill filler))) (define (test2 uvector) (let1 filler (lambda (vec) (u8vector-length uvector)) (make <buffered-input-port> :fill filler)))
- Shiro(2007/07/05 13:10:14 PDT): 上のセッションで、bufとinを潰した後、例えば
次のコードを実行してからgcを何回かかけてみてください。
(let loop ((a 0)) (if (> a 10000) 0 (+ a (loop (+ a 1)))))
私の環境ではこれでgcされます。VMスタックにuvectorへの参照が残っていたのでしょう。 普通のケースではプログラムの進行につれスタックが上書きされるので滅多に 問題にはならないと思いますが、weak-gc robustでない構造へのポインタが そういうふうに残っている場合は注意が必要ですね。
現実に問題が出るケースがあれば教えてください。明示的gcが要求されたら VMスタックをクリアする、みたいにしてもいいかもしれません。
- shinya(2007/07/06 04:30:21 PDT): Shiroさんの示されたコードを入れるとわたしの環境でもGCされました。あるプログラムを実行するとgoshプロセスのメモリ使用量が増え続けるという問題があって、これを原因と思い込んでしまっていたようです。元のプログラムで確認し直したところちゃんとGCされていました。
元のプログラムの問題は環境依存のようでmingw環境で以下のプログラムを実行するとメモリ使用量が増え続けます。
(use gauche.uvector) (use gauche.vport) (define (main args) (while #t (display ".")(flush) (let1 buf (make-u8vector 1000000) (open-input-uvector buf))))
- Shiro(2007/07/06 12:50:31 PDT): むむ。それは別の原因ぽいですね。
inline展開されるbuiltin関数のbindを後から変更したときの動作
(2007/07/02 02:49:36 PDT): compile.scmを読んでいて、どうなんだろう?と思い下記の例を実行するとsiscと動作が異なります。siscと同じ動作にしようと思うと#<subr continuation>を起動したときに、inline展開を剥しまくるか再コンパイルしないといけなくなるので、「現在の動作が仕様」と言ってしまうのが良いかもしれません。
- PowerBook G4
- Mac OS X 10.4.10
- Gauche 0.8.7/ 0.8.10
- ./configure
gosh> (define (f) (let1 x #f (call/cc (lambda (c) (set! x c))) (display (+ 3 4)) x)) f gosh> (define g (f)) 7g gosh> (g) 7g gosh> (define + -) + gosh> (g) 7g
siscだと(g)でdisplayされるのは-1になります。また、(g)の結果が#<subr continuation>ではなくgと表示されるのが面白いですね。 -- dsk
- Shiro(2007/07/02 10:59:25 PDT): これは仕様です。Gauche-develで昔議論になったんですが、 R5RS的にはこういう動作も許されるって結論だったと思います。 ちなみに現在のR6RS draftでは、このようなコード (importしている束縛を 再定義する) は明示的に禁止されています。'+' を再定義したければrnrsモジュールを importする時に '+' だけexcludeするかrenameするかして、名前がぶつからないように しないとだめで、このコードのような曖昧性は排除されます。 (GaucheのR6RSサポート予定についてはGauche-devel / Gauche-devel-jp に 流したメール "R6RS" をご覧ください)
- (2007/07/04 06:32:08 PDT): ご回答ありがとうございます。議論済みなんですね。失礼しました。 http://sourceforge.net/mailarchive/message.php?msg_id=20050828150046.GA32646%40bedna から始まる議論でもっと単純な再現方法がありますね。早速Gauche-develをsubscribeさせて頂きました。 -- dsk
Segmentation fault
2007/06/28 03:42:25 PDT SICPの問題3.23(dequeueを作る)で作ったプログラムを走らせたら Segmentation faultに遭遇しました。
- MacBook Core Duo
- Mac OS X 10.4.10 (Build 8R2218)
- Gauche 0.8.8, 0.8.10 どちらでも
- ./configure --enable-threads=pthreads --enable-multibyte=utf-8
Shiro(2007/07/01 00:55:09 PDT): 再現プログラムはちょっと長いので消しときました。 原因は、errorの出力ルーチンが循環構造のあるオブジェクトをちゃんと 処理していなかったことにありました。これだけで再現します:
gosh> (error "foo" '#0=(#0#)) Segmentation fault
たぶんこれで大丈夫じゃないかな。
--- src/scmlib.scm 16 Apr 2007 03:47:13 -0000 1.13 +++ src/scmlib.scm 1 Jul 2007 07:54:43 -0000 @@ -234,7 +234,7 @@ (if (null? args) (get-output-string p) (begin (display " " p) - (write (car args) p) + (write/ss (car args) p) (loop (cdr args))))))) (define (scan-keys args) (let loop ((args args) @@ -265,9 +265,9 @@ (if (null? msgs) (apply make fmt keys) (apply make fmt - :message (apply format #f msgs) + :message (apply format/ss #f msgs) keys)))) - (else (make <error> :message (apply format #f fmt args)))))) + (else (make <error> :message (apply format/ss #f fmt args)))))) (values error errorf)))
identity が undocumented (0.8.10 and CVS HEAD)
(2007/06/27 04:39:27 PDT):意外なことに、identity関数のエントリーがない!?
- Shiro(2007/06/27 12:54:58 PDT): 公式にはvaluesを使ってくださいってことですね。 値が常に一個であることを明示したければ(lambda (x) x)と書いたっていいわけで、 identity関数の必要性について確信が持てないのがオフィシャルになってない理由です。
- nobsun(2007/06/28 19:24:21 PDT): 個人的には,もちろん values を使えば同じこと
ができるのですが恒等関数という意味で identity という名前の関数があるこ
とはそれなりに重要だと思います.実際,リファレンスマニュアル 9.3.2
Selection and searching in collection にある総称関数 group-collection
の説明のなかで
@deffn {Generic function} group-collection coll &keyword key test @c EN Generalized @code{partition}. Groups elements in @var{coll} into those who has the same key value, and returns the groups as of lists. Key values are calculated by applying the procedure @var{key} to each element of @var{coll}. The default value of @var{key} is @code{identity}. For each element of @var{coll}, @var{key} is applied exactly once. The equal-ness of keys are compared by @var{test} procedure, whose default is @code{eqv?}.
のように identity という関数が説明につかわれています.これを values に 置き換えると何か違和感に「醸される」感があります.(私だけかもしれんけ ど...) - Shiro(2007/06/28 19:48:48 PDT): そうですねぇ。私も何かで「あった方が便利」 と思ってつけたんだと思います。ただ、オフィシャルにしようとすると まず「恒等関数とは」ということをちゃんと考えにゃならない。n-in m-outの Schemeのモデルなら、ふたつ引数を渡されたらふたつ値を返すのが 恒等関数なんじゃないの、だったら (define identity values) と すべきじゃないの、って議論もあるかもしれません。
- nobsun(2007/06/28 21:32:29 PDT): ううむ.n-in m-out がでてくるとちょっと議論が 難しいかなぁ.そういうものが関数なのかという気もするし.そもそも,(foo (values p q)) と書けないのに (define (foo a b) (values x y z)) で 2-in 3-out の関数を定義したことになるのか. って感があるし...
- Shiro(2007/07/01 01:00:38 PDT): ($ foo expr) => (call-with-values (lambda () expr) foo) というマクロはどうだろう。($ foo (values p q)) は (foo p q) になる。 さらに ($ x y z ...) => ($ x ($ y z ...)) って具合にどんどん つなげられるようにしたら、多値をがんがん受け渡してゆく操作が Haskellの$演算子のノリで書けたりするんではなかろうか。 ただ使いどころがあんまり無いかも。
エンディアンを変えたときにwrite-blockが余計なデータを出力する(0.8.10)
koguro(2007/06/16 22:59:15 PDT): write-blockでエンディアンを変更してデータを出力するとデータを余分に出力してしまうようです。
gosh> (use gauche.uvector) #<undef> gosh> (call-with-output-string (lambda (out) (write-block (make-u16vector 1) out 0 -1 'big-endian))) "\0\0\0V\0\0\0\0\0?\0V\0\0" gosh> (call-with-output-string (lambda (out) (write-block (make-u16vector 1) out 0 -1 'little-endian))) "\0\0" (x86の場合)
http-getやhttp-postがキーワード引数 sink と flusher を無視する(CVS HEAD)
び(2007/06/05 21:36:25 PDT): 新しい let-keywords に対応する途中だったのかしら。
--- lib/rfc/http.scm 2 Mar 2007 07:39:10 -0000 1.11 +++ lib/rfc/http.scm 6 Jun 2007 04:30:26 -0000 @@ -125,25 +125,25 @@ (values code headers (and has-content? - (let ((sink (open-output-string)) - (flusher (lambda (sink _) (get-output-string sink)))) + (let-keywords options + ((sink (open-output-string)) + (flusher (lambda (sink _) (get-output-string sink))) + . #f) (receive-body in headers sink flusher)))))))) (let-keywords options - ((sink (open-output-string)) - (flusher (lambda (sink h) (get-output-string sink))) - (host (server->host server)) + ((host (server->host server)) (no-redirect #f) . restopts) (let1 has-content? (not (eq? request 'HEAD)) (if no-redirect - (%send-request request server host request-uri has-content? options) + (%send-request request server host request-uri has-content? restopts) (let loop ((history (list (values-ref (canonical-uri request-uri host) 0))) (server server) (host host) (request-uri request-uri)) (receive (code headers body) - (%send-request request server host request-uri has-content? options) + (%send-request request server host request-uri has-content? restopts) (cond ((and (string-prefix? "3" code) (assoc "location" headers)) => (lambda (loc)
- Shiro(2007/06/23 00:14:25 PDT): パッチ適用しました。
condでsegmentation fault (0.8.10)
% gosh gosh> (cond (1 . 2)) zsh: segmentation fault (core dumped) gosh
ついでにこれも。
(case 0 (else 1 . 2))
- enami(2007/06/04 07:01:52 PDT): compile.scm rev.1.44まではlist?で調べていたのではじかれていたのですね。シンプルなのはテストを追加することでしょうけど、オーバーヘッドが心配?
- Shiro(2007/06/23 00:25:38 PDT): matchに書き直した時にさぼっていたのが理由だと 思います。テストを追加するかわりに (test expr ...) などでマッチさせれば 良いかと。
ext/netでmake testが止まります
0.8.10です。既知の事であれば、すみませんが。
ext/netでのmake checkが、Testing net ...と出たまま戻ってきません。^Cで止めると、以下のようにfailed以降を表示します。
$ uname Linux ****** 2.4.31-v2 #1 SMP Thu Aug 25 15:40:42 JST 2005 i686 i686 i386 GNU/Linux $ cd ext/net ; make check GAUCHE_TEST_RECORD_FILE=../..//test.record ../..//src/gosh -ftest -I. test.scm > test.log Testing net ... failed. discrepancies found. Errors are: test getsockname/getpeername: expects #t => got #f test udp client socket: expects "ABC" => got #<error "unhandled signal 2 (SIGINT)"> $
他のcheck(test)は問題有りません。net周りの仕様が変わったためでしょうか。
- Shiro(2007/06/23 03:29:12 PDT): 手元では再現できません。
ただ、このテストはどんな環境でも必ず成功するとは言えないものなんです。
forkした子プロセスでudp server socketを開いて待ち構えていて、
メインプロセスからパケットを送って返事を待つってところなんですが、
途中でパケットが落ちちゃうとずっと待ちつづけてしまいます
(udpなんで原理的にパケット落ちは常にあり得る)。
ext/net/test.scmの404行目近辺で、(sys-select #f #f #f 300000)
のようにディレイを入れて子プロセスのサーバが立ち上がる余裕を与えてるんですが、 試しに300000を1000000程度にしてやってみてください。 もしかすると子プロセスがちゃんと立ち上がる前にメインプロセスからパケットを 送っちゃってるのかもしれない。
CVS HEAD(2007/05/17 03:01:27 PDT)で2fails
OSはNetBSD current(4.99.19)です。
Testing net ... failed. discrepancies found. Errors are: test getprotobyname: expects (("ip" 0) ("tcp" 6) ("udp" 17)) => got (("ip" 4) ("tcp" 6) ("udp" 17)) test getprotobynumber: expects (#t #t #t) => got (#f #t #t)
ということで2箇所failします。cut-sea:2007/05/17 03:01:27 PDT
- enami(2007/05/23 04:43:49 PDT):/etc/protocolsが変わったからですね。
- ですねぇ。
実際にはIANAの
プロトコル番号0がHOPOPTに変わってしまって、
旧来からある4のIP in IP (encapsulation)がKeyword IPに
なっちゃったのが根本原因ですね。
見ると(last updated 2007-02-12)になってるので移行中ってことでしょうか。 getprotobyname/getprotobynumberに対応するUNIX標準コマンドがあれば テストコードの期待値にそいつを埋め込めば良いのだけど。cut-sea:2007/08/06 01:33:39 PDT - Shiro(2007/08/06 02:14:08 PDT): 他のやつはそうそう変わるものではないでしょうから、 プロトコル番号0が特異点ということで単にテストで使うのを避けることにします。 icmpあたりを使ってみます。
Gauche 0.8.10 のリファレンス 10.10.2「時間に関する問い合わせ」の用語について
Modified Julian Day が「改訂ユリウス日」と訳されていますが、通常は「修正ユリウス日」と訳すと思います。 2007/05/17 02:42:55 PDT
- Shiro(2007/08/09 19:05:17 PDT): done.
Linux/AMD64のsockaddr-addr
Rui (2007/05/14 20:35:58 PDT): Lingrに書いた件。(sockaddr-addr <sockaddr-in6>)のテストがLinux/AMD64で通りません。ntohlがint32_tでなければいけないので。
--- Gauche-0.8.10.orig/ext/net/netlib.stub 2007-04-18 11:08:29.000000000 +0900 +++ Gauche-0.8.10/ext/net/netlib.stub 2007-05-13 20:49:11.000000000 +0900 @@ -88,16 +88,16 @@ (expr "sym_inet6")) (define-cmethod sockaddr-addr ((addr "Scm_SockAddrIn6Class")) - "#define BN_SIZE (16 / SIZEOF_LONG) - ScmSockAddrIn6 *a = (ScmSockAddrIn6*)addr; - u_long values[BN_SIZE]; - u_long *p = (u_long*)a->addr.sin6_addr.s6_addr; + "ScmSockAddrIn6 *a = (ScmSockAddrIn6*)addr; + ScmUInt32 values[4]; + ScmUInt32 *p = (ScmUInt32*)a->addr.sin6_addr.s6_addr; int i; - ScmObj bn; + ScmObj bn = Scm_MakeBignumFromUI(ntohl(*p++)); - for (i = 0; i < BN_SIZE; i++) values[BN_SIZE-i-1] = ntohl(*p++); - bn = Scm_MakeBignumFromUIArray(1, values, BN_SIZE); - SCM_RETURN(Scm_NormalizeBignum(SCM_BIGNUM(bn)));") + for (i=0; i<3; i++) { + bn = Scm_LogIor(Scm_Ash(bn, 32), Scm_MakeBignumFromUI(ntohl(*p++))); + } + SCM_RETURN(bn);") (define-cmethod sockaddr-port ((addr "Scm_SockAddrIn6Class")) " ScmSockAddrIn6 *a = (ScmSockAddrIn6*)addr;
- Shiro(2007/05/22 06:18:09 PDT): 直しました。
- enami(2007/05/23 04:43:49 PDT): values[]は要らないですね。
BrainFuckでコアダンプ(CVS HEAD)
skimuさんのbfc.scmでquine.bをコンパイルして生成したschemeコードを
評価するとセグメンテーションフォールトでコアダンプします。
NetBSD currentとubuntu 7.04で確認。
どうやらコンパイルして生成したコードの尻から3つめの、
少し大きめのloop式の前までは評価できているけど、
そのloop式を含めるとアウトになるようです。cut-sea:2007/05/10 05:42:18 PDT
- Shiro(2007/06/27 12:54:58 PDT): 原因はわかりました。最適化でVMのバグが露見しました。 修正は少しかかります。
- すみません。これはまだだと思っていいですよね?念のため。cut-sea:2007/08/19 23:41:08 PDT
cut-sea@nkisi> gosh -V Gauche scheme interpreter, version 0.8.11 [euc-jp,pthreads] cut-sea@nkisi> ./bfc.scm quine.b | gosh Segmentation fault (core dumped) cut-sea@nkisi>
- Shiro(2007/08/19 23:56:21 PDT): まだです。ちなみに持ち越したバグフィクスに
関してはSourceForgeの方でトラックしてます。
http://sourceforge.net/tracker/?group_id=25227&atid=383866
- そうでしたか。 了解しましたので、改めてこちらに引っ込めておきます。cut-sea:2007/08/20 00:01:16 PDT
rfc.ftp の call-with-ftp-connection (CVS HEAD)
tabe(2007/04/29 20:56:02 PDT) 関数内部で ftp-login に引数を :user でなく :username で渡す必要があるようです。
gosh> (use rfc.ftp) #<undef> gosh> (call-with-ftp-connection "tabe@localhost" ftp-help) WARNING: unknown keyword :user "214-The following commands are recognized.\n ABOR ACCT ALLO APPE CDUP CWD DELE EPRT EPSV FEAT HELP LIST MDTM MKD\n MODE NLST NOOP OPTS PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR\n RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD\n XPWD XRMD" gosh>
パッチ:
Index: lib/rfc/ftp.scm =================================================================== RCS file: /cvsroot/gauche/Gauche/lib/rfc/ftp.scm,v retrieving revision 1.5 diff -c -r1.5 ftp.scm *** lib/rfc/ftp.scm 2 Mar 2007 07:39:10 -0000 1.5 --- lib/rfc/ftp.scm 30 Apr 2007 03:37:44 -0000 *************** *** 73,79 **** (receive (user host port) (uri-decompose-authority uri) (let1 conn (apply ftp-login host (cond-list ! (user @ (list :user user)) (port @ (list :port port)) (#t @ keys))) (unwind-protect (proc conn) --- 73,79 ---- (receive (user host port) (uri-decompose-authority uri) (let1 conn (apply ftp-login host (cond-list ! (user @ (list :username user)) (port @ (list :port port)) (#t @ keys))) (unwind-protect (proc conn)
- Shiro(2007/05/22 04:52:16 PDT): パッチ適用しました。
Bignumと#i1/0の比較がエラーになる (0.8.10)
shinya(2007/04/28 03:22:42 PDT): Bignumとinfinityを比較するとエラーになります
gosh> (< 10000000000000 #i1/0) *** ERROR: can't convert inf to an integer Stack Trace: _______________________________________
パッチ
Index: number.c =================================================================== RCS file: /cvsroot/gauche/Gauche/src/number.c,v retrieving revision 1.146 diff -u -r1.146 number.c --- number.c 26 Mar 2007 23:59:54 -0000 1.146 +++ number.c 28 Apr 2007 10:16:15 -0000 @@ -2318,9 +2318,12 @@ if (r > 0) return 1; return 0; } - if (SCM_BIGNUMP(arg1)) - return Scm_BignumCmp(SCM_BIGNUM(Scm_MakeBignumFromDouble(SCM_FLONUM_VALUE(arg0))), - SCM_BIGNUM(arg1)); + if (SCM_BIGNUMP(arg1)) { + double r = SCM_FLONUM_VALUE(arg0) - Scm_BignumToDouble(SCM_BIGNUM(arg1)); + if (r < 0) return -1; + if (r > 0) return 1; + return 0; + } if (SCM_RATNUMP(arg1)) { double r = SCM_FLONUM_VALUE(arg0) - Scm_GetDouble(arg1); if (r < 0) return -1; @@ -2334,8 +2337,7 @@ return Scm_BignumCmp(SCM_BIGNUM(arg0), SCM_BIGNUM(Scm_MakeBignumFromSI(SCM_INT_VALUE(arg1)))); if (SCM_FLONUMP(arg1)) - return Scm_BignumCmp(SCM_BIGNUM(arg0), - SCM_BIGNUM(Scm_MakeBignumFromDouble(SCM_FLONUM_VALUE(arg1)))); + return -Scm_NumCmp(arg1, arg0); if (SCM_BIGNUMP(arg1)) return Scm_BignumCmp(SCM_BIGNUM(arg0), SCM_BIGNUM(arg1)); if (SCM_RATNUMP(arg1)) {
- Shiro(2007/04/28 13:44:25 PDT): このパッチだとflonumの有効数字より下で 差が出てる場合が怪しくなるので、もうちょっと考えます (どうせinexactなんだから有効数字で丸めていいじゃん、って考えもありかもしれませんが)---いや、Scm_Subとの一貫性を考えるとflonumに丸める方がいいのか。
- Shiro(2007/05/22 04:47:52 PDT): パッチ取り込みました。
mapが多値を返す (0.8.10)
齊藤(2007/04/27 20:48:15 PDT):最後の要素の2個目以降の値がmapの返り値になっているようです。R5RSを読み返しても明確に規定されていることでは無いようですが、奇妙な挙動に見えます。
gosh> (map (cut apply values <>) '((1 2) (3 4) (5 6))) (1 3 5) 6
- skimu R5RS 的には map には多値を返す手続きは渡せませんよ。R5.92RSでも同じ。
Proc must be a procedure that takes as many arguments as there are lists and returns a single value.
- Shiro(2007/04/27 22:16:16 PDT): まあエラーを出すか、ちゃんとチェックして 余分な値をはじくガードをかける方が親切なんですが、Gaucheの設計方針は 「速度を落とすよりはプログラマが自分の足を撃つことを許す」なので… map系は最適化のアイディアがあるので書き直す可能性があり、 その過程でオーバヘッド無くチェックする方法を思いつくかもしれません。
- 齊藤(2007/04/27 22:27:57 PDT):ありゃ、単純な見落としですね。すいません。
拡張ライブラリのコンパイルでwarningが出る (0.8.10)
Shiro(2007/04/26 20:33:31 PDT):
diff -u -r1.23 port.h --- port.h 16 Apr 2007 03:47:13 -0000 1.23 +++ port.h 27 Apr 2007 03:32:59 -0000 @@ -349,21 +349,21 @@ SCM_EXTERN ScmObj Scm_MakeInputStringPort(ScmString *str, int privatep); SCM_EXTERN ScmObj Scm_MakeOutputStringPort(int privatep); -#if defined(GAUCHE_API_0_9) || defined(LIBGAUCHE_BODY) +#if defined(GAUCHE_API_0_8_10) || defined(GAUCHE_API_0_9) || defined(LIBGAUCHE_BODY) SCM_EXTERN ScmObj Scm_GetOutputString(ScmPort *port, int flags); SCM_EXTERN ScmObj Scm_GetOutputStringUnsafe(ScmPort *port, int flags); SCM_EXTERN ScmObj Scm_GetRemainingInputString(ScmPort *port, int flags); +#else /* !defined(GAUCHE_API_0_8_10) && !defined(GAUCHE_API_0_9) && !defined(LIBGAUCHE_BODY) */ +#define Scm_GetOutputString(p) Scm__GetOutputStringCompat(p) +#define Scm_GetOutputStringUnsafe(p) Scm__GetOutputStringUnsafeCompat(p) +#define Scm_GetRemainingInputString(p) Scm__GetRemainingInputStringCompat(p) + /* For backward compatibility */ SCM_EXTERN ScmObj Scm__GetOutputStringCompat(ScmPort *port); SCM_EXTERN ScmObj Scm__GetOutputStringUnsafeCompat(ScmPort *port); SCM_EXTERN ScmObj Scm__GetRemainingInputStringCompat(ScmPort *port); - -#else /* !defined(GAUCHE_API_0_9) && !defined(LIBGAUCHE_BODY) */ -#define Scm_GetOutputString(p) Scm__GetOutputStringCompat(p) -#define Scm_GetOutputStringUnsafe(p) Scm__GetOutputStringUnsafeCompat(p) -#define Scm_GetRemainingInputString(p) Scm__GetRemainingInputStringCompat(p) -#endif /* !defined(GAUCHE_API_0_9) && !defined(LIBGAUCHE_BODY) */ +#endif /* !defined(GAUCHE_API_0_8_10) && !defined(GAUCHE_API_0_9) && !defined(LIBGAUCHE_BODY) */ /*================================================================ * Other type of ports
sys-realpathが使えない (0.8.10)
Shiro(2007/04/26 20:33:31 PDT): ext/sys/auxsys.scmにtypoがあります。
--- auxsys.scm 28 Mar 2007 22:29:56 -0000 1.19 +++ auxsys.scm 23 Apr 2007 08:32:53 -0000 1.20 @@ -52,7 +52,7 @@ ;; define alternatives if the platform doesn't support... (cond-expand - ((not gauche.sys.reaplath) + ((not gauche.sys.realpath) (define sys-realpath #f)) ; make autoload happy (else))
force-output の 定義 (0.8.10)
齊藤(2007/04/21 23:35:29 PDT): slibのreplを使うとプロンプトの表示がおかしいです。現行ではforce-outputは何もしていませんが、flushすればいいんじゃないでしょうか。こんなカンジで。
(define (force-output . arg) (apply flush arg) #t)
- Shiro(2007/05/22 04:39:05 PDT): fixしました。たぶん (define force-output flush) で いいと思う。
プロファイラを使うとポートがGCされない (0.8.10)
shinya(2007/04/21 04:28:54 PDT): プロファイラを利用するとポートがGCされないようです。次のようにして確認しました。
$ cat port-test.scm (use gauche.collection) (define port-table (make-weak-vector 300)) (dotimes (cnt 300) (format #t "cnt:~d active:~d\n" cnt (length (filter identity port-table))) (call-with-output-file #`"test-file-,|cnt|" (lambda (out) (weak-vector-set! port-table cnt out) (write "test" out)))) $ gosh -ptime port-test.scm cnt:0 active:0 cnt:1 active:1 : (省略) : cnt:253 active:253 cnt:254 active:254 active buffered port table overflow
Shiro(2007/08/06 20:34:28 PDT): このコードの場合、call-with-output-fileがoutへのポインタを保持した ScmSubrを生成していて、それがプロファイリングに記録されちゃっているようです。 プロファイラはサンプリングにせよコールカウントにせよオブジェクトへのポインタを 保持するので、GCされないオブジェクトが出てくるのはある意味仕方ないです (ポインタをdisguiseしたりweakに記録することにより「GCされない」問題は解決 しますが、そうするとプロファイル時に記録されたオブジェクトが集計時にGCされて しまっている可能性があり、正しい集計が行えません)。
ただ、この特定の問題に関してはclose時に内部ポートテーブルの内容をクリアする ことで対応可能だと思います。
あと、ScmSubrのサンプリングは名前だけ記録する、とかにしても余分な オブジェクトが生き残ってしまうケースが減らせるかもしれません。
Shiro(2007/08/09 19:05:17 PDT): とりあえず内部ポートテーブルがfullになる問題には 対応しました。
ext/net/net.c の typo (0.8.10)
齊藤(2007/04/20 05:12:37 PDT): 532行目
static void init_winwock(void)