Gauche:Bugs:log17
Gauche 0.9.4以前のバグ
- Windowsコンソール処理の修正と要望 (0.9.4-rc0)
- sys-get-std-handleの後、標準入出力が使えなくなる on Windows (0.9.4-rc0)
- サンプルのgears.scmでキー操作後の角度がおかしい on Windows (0.9.3.3)
- 可変長引数の関数が変な引数を受け取る (e6432c02)
- matchのelseの中でrxmatch-caseのelseを使うとコンパイルエラーになる (64c98029)
- let-values の動作
- (use foo) で強制終了 on Windows (0.9.3.3)
- (#/(a)*\1/ "aa") がマッチしない (6a90c05)
- #/(?(cond)ypat)/ の動作 (cc35730)
- http-compose-query のエラーメッセージ
- current-directory と parameterize (e5ce2abb)
- hmac-sha512の値 (0.9.3.3)
- (case 1 (() #t) (else #f)) がエラーになる (0.9.3.3)
- (/ 複素数 0) がエラーになる (58d2d4615)
- (/ 0) (/ 1 0) 等が +inf.0 になる (58d2d4615)
- (integer? +inf.0) の戻り値 (4a61d3)
- SRFI-19 の閏秒テーブルの更新 (0.9.3.3)
- string-scan-rightの挙動がおかしい (0.9.3.3)
- match-defineが動かない (~0.9.3.3)
- 部分継続の動作が怪しい (0.9.3.2)
- iota に負数を与えたときの errorf のフォーマットがおかしい (0e669e)
- every / stream-every の戻り値(0e669e)
- MacOSX 10.7.3でfork中にGCが起こると"thread_suspend failed"エラーで止まる [0.9.3.2]
- --enable-multibyte=utf8 以外のエンコーディングでconfigureするとドキュメントのビルドに失敗する [0.9.3]
Windowsコンソール処理の修正と要望 (0.9.4-rc0)
h(2014/06/22 12:21:27 UTC):以下は Gauche v0.9.4-rc0 でWindowsのコンソール制御のプログラムを作っていて気がついたものです。
(1)sys-read-console-input を呼ぶとエラーになる
→ Scm_WinHandle の第2引数が '#t になっているが '#f が正しそう。
(2)<win:input-record> の key.virtual-key-code が VirtualScanCode を返してくる
→ VirtualKeyCode が device-independent で、
VirtualScanCode が device-dependent とのこと。
key.virtual-scan-code を追加してみた。
(3)画面クリアとキー入力クリア用のAPIが使いたい(要望)
→ sys-fill-console-output-character
sys-fill-console-output-attribute
sys-flush-console-input-buffer
を追加してみた(難しくて自信なし)。
作成した console.stub と windows.scm のパッチは以下です。
https://gist.github.com/Hamayama/5dc4b376103bc6919bfd
作成したコンソール制御のプログラムは以下です。(テストはWindowsコンソールで花火の表示をします)
https://github.com/Hamayama/mscon
確認環境は Windows XP SP3, Windows 8(64bit) です。
- Shiro(2014/06/22 12:46:57 UTC): ども。自分ではほとんどこのへん使わないので助かります。 sys-fill-console-output-characterですが、1文字しか使わないのであれば 文字列ではなく文字を渡すようにしようかと思いますがそれだとまずいことありますか?
- h(2014/06/22 13:51:27 UTC):文字を渡すでよいと思います。SCM_MBS2WCSで変換が必要かと思いこの関数に1文字だけ渡す方法が分からなくて文字列にしてしまっていました。
- Shiro(2014/06/23 06:24:09 UTC): rc2出しました http://practical-scheme.net/vault/Gauche-mingw-0.9.4-rc2.msi 試してみてください。
- h(2014/06/23 10:46:03 UTC): windows.scm のexport設定が抜けているようです(すいませんパッチのページの下の方に貼っていました)。お手数ですが windows.scm の方も対応をお願いします。
- Shiro(2014/06/24 13:49:43 UTC): ぎゃー見落としてました。コミットしました。
- h(2014/06/25 08:42:44 UTC): ありがとうございます。問題なく動きました。
sys-get-std-handleの後、標準入出力が使えなくなる on Windows (0.9.4-rc0)
h(2014/06/14 05:00:00 UTC):以下のコードを実行すると、標準入力でエラーが発生します。
(use os.windows) (sys-get-std-handle STD_INPUT_HANDLE) (gc) ; GCが起こるような処理であれば何でもよい (read-line)
エラー内容:
*** SYSTEM-ERROR: read failed on #<iport (standard input) 00d6ef50>: Bad file descriptor
コードの2行目を、
(define stdin-handle (sys-get-std-handle STD_INPUT_HANDLE))
としてハンドルを保持しておくようにすると、エラーは発生しなくなります。
同様の現象は、標準出力や標準エラー出力でも発生します。
環境は、Windows XP SP3, Windows 8(64bit), Gauche v0.9.3.3, Gauche v0.9.4-rc0 です。
- Shiro(2014/06/15 10:47:55 UTC): sys-get-std-handleでハンドルをコピーするようにしてみました。 (コミット3daa0f2)。近いうちにrc2出します。
- h(2014/06/15 14:25:44 UTC):ありがとうございます。戻り値のハンドルは数値ではなくて何かオブジェクトだったのですね。
サンプルのgears.scmでキー操作後の角度がおかしい on Windows (0.9.3.3)
h(2014/05/26 06:05:08 UTC):インストール時にできたexamplesフォルダのgears.scmを実行すると、歯車の3D表示が出ます。
矢印キーで表示の角度を変えられるのですが、変更後しばらくすると角度がぴょこぴょこと変わる現象が出ます。
gosh を -fno-inline を付けて起動した場合は発生しないようです。
Windows XP SP3 と Windows 8 で確認しました。
- Shiro(2014/05/26 07:20:01 UTC): 「しばらく」ってどのくらいの時間ですか? あと、変わる角度に規則性みたいなものは見られますか? 手元(HEAD on Vista)では再現しないのですが、 角度部分は特にシステムに依存するようにも見えないし、謎です。
- もうじき0.9.4-rc1のインストーラをアップロードするので、そしたらそれで試して頂いて、 直ってたらよし、直ってなかったら機種依存部分の切り分けに入りましょう。
h(2014/05/26 10:39:12 UTC):gears.scmを編集して、
206行目に (print #`"rotx ,*view-rotx*") を挿入し、
283行目の (set! *view-rotx* (fmod (+ *view-rotx* 5.0) 360)) (q)) を、
(set! *view-rotx* (fmod (+ *view-rotx* 5.0) 360)) (print #`"rotx ,*view-rotx*") (q)) に変更しました。
これを実行して上を1回だけ押すと、コマンドプロンプト側の表示は以下のようになりました。
見ていると3~4秒に1回くらい角度が変わります。
角度は、gears.scmを実行するたびに変わるようです。
また、上を1回も押さなければ、rotx 20.0 のままで正常です。
2438 in 5.0 seconds = 487.6 FPS rotx 20.0 rotx 25.0 2591 in 5.0 seconds = 518.2 FPS rotx -703.0 2659 in 5.0 seconds = 531.8 FPS rotx -542.0 2680 in 5.001 seconds = 535.8928214357128 FPS rotx -381.0 2574 in 5.0 seconds = 514.8 FPS rotx -220.0 2510 in 5.0 seconds = 502.0 FPS rotx -619.0 2485 in 5.001 seconds = 496.90061987602473 FPS rotx -458.0
Shiro(2014/05/26 10:49:02 UTC): ますます謎の挙動ですね。*view-rotx*が正規ルート以外で 更新されてる? にしても値が綺麗すぎるような。とりあえず、現在のHEADをインストーラに パッケージしたものを http://practical-scheme.net/vault/Gauche-mingw-0.9.4-rc0.msi に上げたので、良ければこれで試して頂けますか。
h(2014/05/26 13:50:09 UTC):対応ありがとうございます。上記のインストーラで、
Windows XP と Windows 8 の両方で、正常に動作することを確認しました。
(Windows XP のPCは、OS付属の Windows Installer がこわれていたらしく、
インストーラを実行すると「msiexec.exe でハンドルされていない例外が発生しました。」
というようなエラーが出ました。これは、Windows Installer を Microsoftのサイトから取ってきて
入れなおしたところ、インストールできました。
(http://www.microsoft.com/ja-jp/download/details.aspx?id=8483
から WindowsXP-KB942288-v3-x86.exe をダウンロードして実行))
可変長引数の関数が変な引数を受け取る (e6432c02)
(2014/03/16 19:36:09 UTC): 以下のコードで、 call が変な引数を受け取ります
(let ()
(define (call object message . args)
(unless (list? args)
(error "Strange arguments: "
`(call (object ,object) (message ,message) (args ,args))))
(and-let* ((it (object message)))
(apply it object args)))
(define (foo)
(define (bar) (lambda _ (lambda _2 'bar)))
(define (baz x) (call x 'baz))
(define (baz2 x) (call x 'baz))
(define (test x) (baz x))
(define (test2 x) (baz x))
(test (bar)))
(foo))
*** ERROR: Strange arguments: (call (object #<compiled-code load@0x7f4a7bf041b0>) (message #<closure (call bar)>) (args baz))
- Shiro(2014/03/16 22:58:47 UTC): ローカル関数の呼び出し前に可変長引数のfoldingが ちゃんと行われていませんね… コンパイラのバグっぽい。
- Shiro(2014/05/27 02:33:03 UTC): 原因はわかった。が、どうやって直そうかなあ。根本原因:
- call site解析の後では、ローカルに作られるlambdaノードは、それを呼び出しているcallノードのリストを持つ
- クロージャ解析後、そのlambdaノードがインライン化できないと判断された場合、クロージャを作るとともに、それを呼び出しているcallノードを変形して、rest引数の畳み込みなどを行う
- 一方、ローカル関数がインライン展開される時に、そのbodyがコピーされる場合がある。
- もし、コピーされるbodyの中に、上記の「インライン化できないlambdaを呼び出しているcallノード」があった場合、コピー後のcallノードは該当lambdaの「呼び出し元リスト」には現れないので、引数の調整対象から漏れてしまう
- Shiro(2014/06/01 13:05:50 UTC): 泥縄的に直した (dd7a023)。
matchのelseの中でrxmatch-caseのelseを使うとコンパイルエラーになる (64c98029)
koguro(2013/12/31 12:38:03 UTC): マクロ展開器の既知のバグかもしれませんが、以下のコードでコンパイルエラーになります。
% gosh
gosh> (use util.match)
#<undef>
gosh> (use gauche.regexp)
#<undef>
gosh> (gauche-version)
"0.9.4_pre3"
gosh>
(match '()
(('foo)
0)
(else
(rxmatch-case "bbb"
(#/aaa/ (_)
1)
(else
2
;; (begin 2)
))))
*** ERROR: Compile Error: malformed #<identifier gauche.regexp#rxmatch-if>: (#<identifier gauche.regexp#rxmatch-if> (#<identifier gauche.regexp#and> #0=#<identifier gauche.regexp#strp> (#<identifier gauche.regexp#rxmatch> else #1=#<identifier gauche.regexp#temp>)) 2 (#<identifier gauche.regexp#begin>) (#<identifier gauche.regexp#rxmatch-case> #t #1# #0#))
"(standard input)":5:(match '() (('foo) 0) (else (rxmatch ...
Stack Trace:
_______________________________________
0 (eval expr env)
At line 179 of "/usr/local/share/gauche-0.9/0.9.4_pre3/lib/gauche/interactive.scm"
Shiro(2013/12/31 21:46:38 UTC): なるほどこれはわかりにくい。
matchはelseを特別扱いしません。なのでmatchのelse節は 単にフォーム全体を変数elseに束縛する動作になります。rxmatch-caseはhygienic macroなので、elseが特別な効果を 発揮するのはそれがグローバルな束縛をさしている時だけです。今回、elseはmatchによってローカルに束縛されているので、意味のあるelseとは認識されず、 この節全体が(regexp binding form ...)のパターンに一致するものと 考えてrxmatch-ifの呼び出しへと展開されます。rxmatch-ifの呼び出しでは、bindingを期待してるところに2が 渡ってくるのでmalformed syntaxエラーになります。
たまたま(else 2) だったからsyntax errorになりましたが、
(else (foo bar)) だったとすれば(foo bar)部分がbindingと
解釈されてコンパイルは通り、実行時のエラーになります (rxmatch-ifが
regexpを期待してるところに、matchで束縛された値が渡ってくるから)
これはエラーの出し方を何とか頑張るしかないかなあ。今の出力では何が原因だかさっぱりですから。
- koguro(2013/12/31 23:12:09 UTC): matchってelseは特別扱いしなかったんですね。勘違いしていました。
- Shiro(2014/01/01 03:34:13 UTC): シンボルひとつだと必ずマッチが成功するので elseとして動作しちゃうんですよね。私もたまに勘違いします。
let-values の動作
2013/12/23 07:25:27 UTC: 中国人剰余定理を試すための以下のコードでエラーになりました。 SagittariusとNormalでは動作しました。コード、おかしいですか? sasagawa?
gosh -V Gauche scheme shell, version 0.9.3.3 [utf-8,wthreads], i686-pc-mingw32
(define (ex-gcd a b)
(ex-gcd1 a b 1 0 0 1))
(define (ex-gcd1 r0 r1 a0 a1 b0 b1)
(if (= r1 0)
(values a0 b0 r0)
(let* ((q1 (quotient r0 r1))
(r2 (remainder r0 r1))
(a2 (- a0 (* q1 a1)))
(b2 (- b0 (* q1 b1))))
(ex-gcd1 r1 r2 a1 a2 b1 b2))))
(define (chinese a1 a2 m1 m2)
(let-values (((y t c)(ex-gcd m1 m2)))
(unless (= c 1) (error "chinese require coprime numbers"))
(let ((x (+ a1 (* (- a2 a1) y m1))))
(if (positive? x)
x
(modulo x (* m1 m2))))))
gosh> (chinese 30910 44464 67409 73679)
*** ERROR: unbound variable: t
Stack Trace:
__
- Shiro(2013/12/23 07:31:45 UTC): let-valuesが標準に入ったのはR6RSからなので、 Gaucheはデフォルトでは(use srfi-11)しないと使えません。
- sasagawa?(2013/12/23 07:37:16 UTC): お騒がせしました。動きました。
gosh> (use srfi-11) #<undef> gosh> #t gosh> (chinese 30910 44464 67409 73679) 123456789 gosh>
(use foo) で強制終了 on Windows (0.9.3.3)
2012/09/29 18:05:37 UTC: windows 用バイナリなんですが、存在しないモジュールを読み込むとエラーが出たあと強制終了します(require も同様)。
- Shiro(2012/09/29 22:38:38 UTC): もうちょい環境を教えてください。うちのVista SP2 (32bit)では再現しません。
h(2013/10/18 17:02:06 UTC):同じ現象が起きています。 Gauche-mingw-0.9.3.3.msiをWindows XP SP3にインストールしています。 コマンドプロンプトで、
gosh> (use foo)
を実行すると、
*** ERROR: Compile Error: cannot find "foo" in ("C:\\Program Files\\Gauche\\shar
e\\gauche-0.9\\site\\lib" "C:\\Program Files\\Gauche\\share\\gauche-0.9\\0.9.3.3
\\lib" "C:\\Program Files\\Gauche\\share\\gauche/site/lib" "C:\\Program Files\\G
auche\\share\\gauche/0.9/lib")
"(stdin)":1:(use foo)
Stack Trace:
と表示した後に、 「gosh.exe [13232] でハンドルされていない Win32 の例外が発生しました。」 というように実行エラーのウィンドウが出ます。
同様に、
gosh> (car)
を実行すると、
*** ERROR: Compile Error: wrong number of arguments: car requires 1, but got 0 "(stdin)":2:(car) Stack Trace:
と表示した後に、 「gosh.exe [13352] でハンドルされていない Win32 の例外が発生しました。」 というように実行エラーのウィンドウが出ます。
一方、
gosh> (x)
では、
*** ERROR: unbound variable: x Stack Trace:
と表示しますが、実行エラーのウィンドウは出ません。
- Shiro(2013/10/19 03:59:06 UTC): ビルド環境の有無で差が出てるかな。古いXPマシンが 確かまだあるので確かめてみます。
h(2013/12/13 18:17:23 UTC):現象の発生するPCでコンパイルしたところエラーが出なくなりました。 以下はそのメモです。
Windows XP SP3のPCで作業
(1)事前に
Gauche-mingw-0.9.3.3.msi
をインストール済み
(C:\Program Files\Gauche)
Gaucheのショートカットを起動して、
(use foo) または (car)
で実行エラーになることを確認
(2)MinGWをインストール
MinGWのダウンロードページ
http://sourceforge.net/projects/mingw/files/
から mingw-get-setup.exe (2013-10-04版) をダウンロードしてきて実行
Basic Setup で以下を選択
mingw-developer-toolkit (v2013072300)
mingw32-base (v2013072200)
mingw32-gcc-g++ (v4.8.1-4)
msys-base (v2013072300)
All Packages で以下を追加選択
mingw32-libz dev (v1.2.8-1)
メニューの Installation - Apply Changes を選択して、
Applyボタンをクリックしてインストール
システム環境変数PATHを編集し、最後のところに
;C:\MinGw\bin;C:\MinGW\msys\1.0\bin
を追加
C:\MinGW\msys\1.0\msys.batを実行
すると、以下のフォルダができる
C:\MinGW\msys\1.0\home\(ユーザ名)
C:\MinGW\msys\1.0\home\(ユーザ名) に
テキストエディタ(TeraPad)で .bashrc を作成。内容は以下
alias ls='ls --color=auto --show-control-chars'
C:\MinGW\msys\1.0\home\(ユーザ名) に
テキストエディタ(TeraPad)で .profile を作成。内容は以下
source .bashrc
C:\MinGW\msys\1.0\home\(ユーザ名) の
.inputrc を テキストエディタ(TeraPad)で編集。変更内容は以下
set output-meta off → on
set convert-meta on → off
C:\MinGW\msys\1.0\etc に
テキストエディタ(TeraPad)で fstab を作成(拡張子なし)。内容は以下
c:/mingw /mingw
(3)Gaucheのソースをダウンロード
http://practical-scheme.net/gauche/download-j.html
から Gauche-0.9.3.3.tgz をダウンロードしてきて、解凍ソフト(Lhaplus)で、
c:\Gaucheの下に展開
c:\Gauche\Gauche-0.9.3.3 ができた。
(4)c:\Gauche\Gauche-0.9.3.3\src\mingw-dist.sh の内容を一部変更
utf8 → sjis
(5)c:\Gauche\Gauche-0.9.3.3\ext\net のコンパイルエラー対応
c:\Gauche\Gauche-0.9.3.3\src\gauche\win-compat.h の
#include <windows.h> の前に以下の2行を追加
#include <winsock2.h>
#define HAVE_STRUCT_SOCKADDR_STORAGE
( -lws2_32 で winsock2 のライブラリを使う場合、
windows.h 内で古い winsock.h を読み込んでいるため、
その前に winsock2.h を読み込む必要があるらしい )
(6)Gaucheをコンパイル
コマンドプロンプトを開いて以下を実行
bash
cd /c/Gauche/Gauche-0.9.3.3/
src/mingw-dist.sh
(7)テストを実行
コマンドプロンプトを開いて以下を実行
bash
cd /c/Gauche/Gauche-0.9.3.3/
make check
(結果をファイルにも残すときは、
make check 2>&1 | tee test_result.txt
のようにする)
結果は、
Total: 12569 tests, 12561 passed, 8 failed, 0 aborted.
となり、8件失敗しているみたい。。。
Testing file.util ... failed.
discrepancies found. Errors are:
test touch-file :time :type: expects (60000 50001) => got (4294940896 50001)
test touch-file :time :type: expects (60000 70000) => got (4294940896 4294950896)
Testing gettext ... failed.
discrepancies found. Errors are:
test get-en: "Menu|File|Quit": expects "Quit" => got "Menu|File|Quit"
test gettext-en: "Menu|File|Quit": expects "Quit" => got "Menu|File|Quit"
test dcgettext-en: "Menu|File|Quit": expects "Quit" => got "Menu|File|Quit"
test get-en: "Menu|File|Quit": expects "Quit" => got "Menu|File|Quit"
test gettext-en: "Menu|File|Quit": expects "Quit" => got "Menu|File|Quit"
test dcgettext-en: "Menu|File|Quit": expects "Quit" => got "Menu|File|Quit"
とのことだが、よく分からない。。。
(8)生成したファイルをコピー
生成した
C:\Gauche\Gauche-mingw-dist\Gauche
の中身を、すべて
C:\Program Files\Gauche
に上書き
(9)起動確認
Gaucheのショートカットを起動して、
(use foo) または (car)
で実行エラーにならないことを確認
また、この環境で、以前の gosh.exe は、
(use foo) または (car)
で実行エラーになることを確認
(その他)
(6)でbashを起動しないと、make等でハングアップした。
シェルを起動しないといけないことに、なかなか気付けなかった。。。
(4)でutf-8のままにして、minttyで動かそうとしてみたが、
インタラクティブモードでバックスペースで削除したりすると、
入力がおかしくなった。
Windowsのコンソールプログラムでsjis以外に対応するのは相当難しいのか。。。
あきらめてsjisにした。。。
- Shiro(2013/12/14 08:00:19 UTC): 検証ありがとうございます。Windowsランタイムの
バージョンに依存する方法でAPIを呼んじゃってるのかなあ?
Mingw上のテストで出るエラーについてはHEADで対応済みです (別のエラーがまだ出るのですが)。
h(2014/01/11 11:52:00 UTC):コンパイルすれば正常動作したのでもうよいのですが、 以下は元のgosh.exeのエラーの原因について、気になってもう少し調べたものです。
h(2013/12/18 00:29:28 UTC):gdbを使って、元のgosh.exeでエラーを出させると以下になりました。
Program received signal SIGSEGV, Segmentation fault.
0x77be554a in msvcrt!_abnormal_termination ()
from C:\WINDOWS\system32\msvcrt.dll
それで、ネット上で調べたところ、以下の情報がありました。
(a) http://mingw.5.n7.nabble.com/USE-32BIT-TIME-T-and-legacy-MSVCRT-DLL-td31533.html (b) http://mingw.5.n7.nabble.com/quot-msvcrt-abnormal-termination-quot-in-XP-but-not-win7-td29464.html (c) http://gcc.1065356.n5.nabble.com/gcc-auto-omit-frame-pointer-vs-msvc-longjmp-td700403.html (a)は msvcrt.dll にはOSによって非互換性があるという情報です(2013-5-22)。 (b)は Windows XP で類似のエラーが発生した件の情報です(2012-9-30)。 setjmp/longjmpの問題ではないかとのことでした。 (c)は gcc 4.6 で setjmp の呼び出しを修正したという情報です(2011-10-25)。 古い msvcrt.dll の setjmp には、frame-pointer が必要だが、 gcc の最適化等により -fomit-frame-pointer オプションがONになって、 frame-pointer が設定されない場合がある。 このため、32ビットのsetjmpの場合は、常に frame-pointer を設定するように修正した。 ということのようです。
実際に gdb で longjmp にブレークポイントを貼って元のgosh.exeを実行すると、
確かに msvcrt!longjmp → msvcrt!_abnormal_termination → エラー(SIGSEGV)
という流れになっていました。(ただし、longjmp 自体は何度も呼ばれていて、
エラーにならないケースも多いようでした。)
また、発生箇所で逆アセンブルすると 0x77be554a <+51>: mov 0x8(%ebp),%ecx
というところでエラーになっており、確かにフレームポインタ ebp の値が不正(0x0)になっているようでした。
以上のことから、今回のエラーは、Windows XP の msvcrt.dll の setjmp/longjmp の内部動作と、
MinGWのgccの出力するコードに起因するものだと思います。
そして、新しいMinGWのgcc(v4.6.2以降?)では修正されているのだと思います。
(#/(a)*\1/ "aa") がマッチしない (6a90c05)
leque(2013/11/08 02:39:47 UTC):
gosh> (#/(a)*\1/ "aa") #f
サブマッチがずれているみたいです。
gosh> (#/(a)*a/ "aaa") #<<regmatch> 0x10071c420> gosh> ((#/(a)*a/ "aaa") 1) "aa" ;; ← "a" のはず
パッチ: https://gist.github.com/leque/7365349
- Shiro(2013/11/10 23:49:49 UTC): Fixed. Mahalo.
#/(?(cond)ypat)/ の動作 (cc35730)
leque(2013/10/19 10:00:41 UTC): #/(?(cond)ypat)/ は #/(?(cond)ypat|)/ と同じ意味だと思うのですが、そのようになっていません。例えば、 http://www.pcre.org/pcre.txt の "Checking for a used subpattern by number" の例がマッチしません。
gosh> (#/(\()?[^()]+(?(1)\)|)/ "ab") #<<regmatch> 0x10071c3f0> gosh> (#/(\()?[^()]+(?(1)\)|)/ "(ab)") #<<regmatch> 0x10071c0c0> gosh> (#/(\()?[^()]+(?(1)\))/ "(ab)") #<<regmatch> 0x100722ab0> gosh> (#/(\()?[^()]+(?(1)\))/ "ab") ;; ←これもマッチしてほしい #f
test/regexp.scm の (test-re #/(?(?<=a)b)/ "ab" '("b")) 等も cl-ppcre 等と食い違っています( '("") になるはず)。
* (ql:quickload :cl-ppcre) * (cl-ppcre:scan-to-strings "(?(?<=a)b)" "ab") "" #()
パッチ: https://gist.github.com/leque/7053723
- Shiro(2013/10/21 06:30:23 UTC): Fixed. mahalo.
http-compose-query のエラーメッセージ
ryoakg(2013/08/22 12:37:11 UTC):
gosh> (use rfc.http) #<undef> gosh> (http-compose-query "abc" '((1 2 3 4))) *** ERROR: invalid request-uri form: ~s ((1 2 3 4))
http-compose-query の中の query-1 で
errorf じゃなくて error が使われているので、
引数がフォーマットされないで ~s がそのまま出ている様でした。
- Shiro(2013/08/23 02:15:25 UTC): fixed. mahalo.
current-directory と parameterize (e5ce2abb)
leque(2013/02/11 05:25:16 UTC): file.util の current-directory が変更時にもとのディレクトリを返してくれると parameterize できてうれしいと思うのですがどうでしょう? (Chez Scheme や Racket では current-directory は parameter になっているようです)
現在の動作:
gosh> (gauche-version)
"0.9.4_pre3"
gosh> (use gauche.parameter)
#<undef>
gosh> (use file.util)
#<undef>
gosh> (current-directory)
"/private/tmp"
gosh> (current-directory "/var")
#<undef>
gosh> (parameterize ((current-directory "/")) (current-directory))
*** ERROR: directory name should be a string #<undef>
Stack Trace:
_______________________________________
0 (%restore-parameter P S)
[unknown location]
1 (^ () (set! L (%restore-parameter P S)))
[unknown location]
2 (eval expr env)
At line 173 of "/usr/local/share/gauche-0.9/0.9.4_pre3/lib/gauche/interactive.scm"
パッチ:
diff --git a/doc/modgauche.texi b/doc/modgauche.texi
index 2282775..9d23d8e 100644
--- a/doc/modgauche.texi
+++ b/doc/modgauche.texi
@@ -8305,7 +8305,8 @@ netdbインタフェースのScheme APIは必要な箇所ではこれらの関
A @emph{parameter} is something like a stateful procedure that takes zero or
one argument.
If no argument is given, the parameter returns the current value it is keeping.
-If single argument is given, it will be the current value of the parameter.
+If single argument is given, it will be the current value of the parameter,
+and the previous value is returned.
A parameter has several advantages over global variables to store
states.
@c JP
diff --git a/doc/modutil.texi b/doc/modutil.texi
index 2e7c070..a409410 100644
--- a/doc/modutil.texi
+++ b/doc/modutil.texi
@@ -4007,7 +4007,8 @@ Gaucheでは@emph{両方の}名前を提供することにしました。
@c EN
When called with no argument, this returns the pathname of the current
working directory. When called with a string argument @var{new-directory},
-this sets the current working directory of the process to it.
+this sets the current working directory of the process to it,
+and returns the previous working directory.
If the process can't change directory to @var{new-directory}, an error is
signaled.
@@ -4016,7 +4017,8 @@ implementations.
@c JP
引数無しで呼ばれた場合、カレントディレクトリを返します。
文字列@var{new-directory}が与えられた場合はプロセスのカレントディレクトリを
-@var{new-directory}に変更します。変更が出来なかった場合はエラーとなります。
+@var{new-directory}に変更し、変更前のカレントディレクトリを返します。
+変更が出来なかった場合はエラーとなります。
この関数はChezSchemeやMzSchemeなどいくつかのScheme処理系に見られます。
@c COMMON
diff --git a/libsrc/file/util.scm b/libsrc/file/util.scm
index f9a65de..852b16f 100644
--- a/libsrc/file/util.scm
+++ b/libsrc/file/util.scm
@@ -92,7 +92,10 @@
(define (current-directory :optional (newdir #f))
(match newdir
[#f (sys-getcwd)]
- [(? string?) (sys-chdir newdir)]
+ [(? string?)
+ (begin0
+ (sys-getcwd)
+ (sys-chdir newdir))]
[_ (error "directory name should be a string" newdir)]))
(define (home-directory :optional (user (sys-getuid)))
- Shiro(2013/02/11 06:46:58 UTC): どうしようかなあ。カレントディレクトリはプロセスワイドなので
parameterとセマンティクスが違うんですよ。他の処理系との互換性を考えて妥協するという
選択肢もありますが、個人的には
with-directoryとか別の名前にしたいところです。 - leque(2013/02/11 11:52:34 UTC): あー、セマンティクスまで考えていませんでした。 Racket だと current-directory は単純な parameter で、 (current-directory newdir) した時点では chdir しないみたいです。下手に見た目を合わせてもどこかでハマりそうなので取り下げます。
- Shiro(2013/02/11 18:46:10 UTC): 一時的にchdirして戻す、という機能自体は便利なので、 なんか足しときます。
hmac-sha512の値 (0.9.3.3)
es (2012/12/04 13:18:57 UTC):
rfc/hmac.scm において (block-size 64) と決め打ちになっているため、 sha512 や sha384 が渡された場合に違う値が返るようです。 (左の二つはブロックサイズが128の模様です。) パッチがなくてすみませんがご報告致します。
- Shiro(2013/01/07 04:13:40 UTC): block sizeの64は決め打ちではなくデフォルト値で、 キーワード引数でオーバライドできますが、クラスが指定されれば決まるものなので デフォルト値を<sha512>などのクラスの方に持たせるように変更しました。
(case 1 (() #t) (else #f)) がエラーになる (0.9.3.3)
leque (2012/11/29 04:46:43 UTC):
gosh> (case 1 (() #t) (else #f)) *** ERROR: Compile Error: syntax-error: bad clause in case: (case 1 (() #t) (else #f))
RnRS 的には case の <clause> は ((<datum1> ...) <expression1> <expression2> ...) なのでエラーにならず #f が返るべきだと思います。
leque(2013/01/01 15:41:54 UTC) こんな感じでしょうか
diff --git a/src/compile.scm b/src/compile.scm
index 9a7912e..19162b1 100644
--- a/src/compile.scm
+++ b/src/compile.scm
@@ -2088,13 +2088,15 @@
[((elts exprs ...) . rest)
(let ([nelts (length elts)]
[elts (map unwrap-syntax elts)])
- (unless (> nelts 0) (error "syntax-error: bad clause in case:" form))
($if (car cls)
- (if (> nelts 1)
- ($memv #f ($lref tmpvar) ($const elts))
- (if (symbol? (car elts))
- ($eq? #f ($lref tmpvar) ($const (car elts)))
- ($eqv? #f ($lref tmpvar) ($const (car elts)))))
+ (case nelts
+ [(0) ($const-f)]
+ [(1)
+ (if (symbol? (car elts))
+ ($eq? #f ($lref tmpvar) ($const (car elts)))
+ ($eqv? #f ($lref tmpvar) ($const (car elts))))]
+ [else
+ ($memv #f ($lref tmpvar) ($const elts))])
(match exprs
;; (elts => proc) -- SRFI-87 case clause
[((? (cut global-eq? <> '=> cenv)) proc)
diff --git a/test/primsyn.scm b/test/primsyn.scm
index 4b40d7e..630486f 100644
--- a/test/primsyn.scm
+++ b/test/primsyn.scm
@@ -43,6 +43,9 @@
(prim-test "case" #t (lambda () (case (+ 2 3) ((1 3 5 7 9) #t) ((0 2 4 6 8) #f))))
(prim-test "case" #t (lambda () (undefined? (case 1 ((2 3) #t)))))
+(prim-test "case" #t (lambda () (case 1 (() #f) ((1) #t))))
+(prim-test "case" #t (lambda () (case 1 (() #f) (else #t))))
+(prim-test "case" #t (lambda () (undefined? (case 1 (() #t)))))
(prim-test "case (srfi-87)" 0 (lambda () (case (+ 2 3) ((1 3 5) 0) (else => values))))
(prim-test "case (srfi-87)" 6 (lambda () (case (+ 2 3) ((1 3 5) => (cut + 1 <>)) (else => values))))
(prim-test "case (srfi-87)" 5 (lambda () (case (+ 2 3) ((2 4 6) 0) (else => values))))
- Shiro(2013/01/07 04:13:40 UTC): applyしました。まはろ。
(/ 複素数 0) がエラーになる (58d2d4615)
leque(2012/10/07 07:48:21 UTC):
gosh> (gauche-version) "0.9.3.3" gosh> (/ 1+2i 0) *** ERROR: Compile Error: real number required, but got 1.0+2.0i ... gosh> (/ 1+2i 0.0) *** ERROR: Compile Error: real number required, but got 1.0+2.0i ...
パッチ:
diff --git a/src/number.c b/src/number.c
index d4d0479..a379303 100644
--- a/src/number.c
+++ b/src/number.c
@@ -2129,7 +2129,8 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
}
if (SCM_COMPNUMP(arg0)) {
if (SCM_INTP(arg1)) {
- if (SCM_EXACT_ZERO_P(arg1)) goto anormal;
+ // NB: Gauche has no exact compnum
+ if (SCM_EXACT_ZERO_P(arg1)) goto anormal_comp;
if (SCM_EXACT_ONE_P(arg1)) return arg0;
return Scm_MakeComplex(SCM_COMPNUM_REAL(arg0)/SCM_INT_VALUE(arg1),
SCM_COMPNUM_IMAG(arg0)/SCM_INT_VALUE(arg1));
@@ -2140,7 +2141,7 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
SCM_COMPNUM_IMAG(arg0)/z);
}
if (SCM_FLONUMP(arg1)) {
- if (SCM_FLONUM_VALUE(arg1) == 0.0) goto anormal;
+ if (SCM_FLONUM_VALUE(arg1) == 0.0) goto anormal_comp;
return Scm_MakeComplex(SCM_COMPNUM_REAL(arg0)/SCM_FLONUM_VALUE(arg1),
SCM_COMPNUM_IMAG(arg0)/SCM_FLONUM_VALUE(arg1));
}
@@ -2206,6 +2207,20 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
if (s < 0) return SCM_NEGATIVE_INFINITY;
else return SCM_POSITIVE_INFINITY;
}
+ anormal_comp:
+ {
+ double r0 = SCM_COMPNUM_REAL(arg0);
+ double i0 = SCM_COMPNUM_IMAG(arg0);
+ double r =
+ r0 > 0.0 ? SCM_DBL_POSITIVE_INFINITY
+ : r0 < 0.0 ? SCM_DBL_NEGATIVE_INFINITY
+ : SCM_DBL_NAN;
+ double i =
+ i0 > 0.0 ? SCM_DBL_POSITIVE_INFINITY
+ : i0 < 0.0 ? SCM_DBL_NEGATIVE_INFINITY
+ : SCM_DBL_NAN;
+ return Scm_MakeComplex(r, i);
+ }
do_complex:
{
double r1 = SCM_COMPNUM_REAL(arg1);
diff --git a/test/number.scm b/test/number.scm
index bf59d43..defed59 100644
--- a/test/number.scm
+++ b/test/number.scm
@@ -1237,6 +1237,21 @@
(test* "division by zero" #t (nan? (divide. 0.0 0.0)))
(test* "division by zero" +inf.0 (divide. 0.5 0))
+(test* "division by zero" +inf.0+inf.0i (/ 1+2i 0.0))
+(test* "division by zero" +inf.0-inf.0i (/ 1-2i 0.0))
+(test* "division by zero" -inf.0+inf.0i (/ -1+2i 0.0))
+(test* "division by zero" -inf.0-inf.0i (/ -1-2i 0.0))
+
+(test* "division by zero" #t
+ (let ((r (/ 0+1i 0)))
+ (and (nan? (real-part r))
+ (= (imag-part r) +inf.0))))
+
+(test* "division by zero" #t
+ (let ((r (/ 0+1i 0.0)))
+ (and (nan? (real-part r))
+ (= (imag-part r) +inf.0))))
+
(define (almost=? x y)
(define (flonum=? x y)
(let ((ax (abs x)) (ay (abs y)))
- Shiro(2012/10/07 18:19:29 UTC): 適用しました。まはろ。
(/ 0) (/ 1 0) 等が +inf.0 になる (58d2d4615)
leque(2012/10/07 07:41:28 UTC): exact な 0 の場合はエラーになってほしいような気がします。
gosh> (gauche-version) "0.9.3.3" gosh> (/ 0) +inf.0 gosh> (/ 1 0) +inf.0
パッチ:
diff --git a/src/number.c b/src/number.c
index dcd7561..d4d0479 100644
--- a/src/number.c
+++ b/src/number.c
@@ -554,6 +554,9 @@ ScmObj Scm_MakeRatnum(ScmObj numer, ScmObj denom)
if (!SCM_INTEGERP(denom)) {
Scm_Error("denominator must be an exact integer, but got %S", denom);
}
+ if (SCM_EXACT_ZERO_P(denom)) {
+ Scm_Error("attempt to calculate a division by zero");
+ }
r = SCM_NEW(ScmRatnum);
SCM_SET_CLASS(r, SCM_CLASS_RATIONAL);
r->numerator = numer;
@@ -572,6 +575,9 @@ ScmObj Scm_MakeRational(ScmObj numer, ScmObj denom)
if (!SCM_INTEGERP(denom)) {
Scm_Error("denominator must be an exact integer, but got %S", denom);
}
+ if (SCM_EXACT_ZERO_P(denom)) {
+ Scm_Error("attempt to calculate a division by zero");
+ }
if (SCM_EXACT_ONE_P(denom)) return numer;
if (SCM_EXACT_ZERO_P(numer)) return SCM_MAKE_INT(0);
else return Scm_ReduceRational(Scm_MakeRatnum(numer, denom));
@@ -2000,7 +2006,10 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
if (SCM_INTP(arg0)) {
if (SCM_INTP(arg1)) {
- if (SCM_EXACT_ZERO_P(arg1)) goto anormal;
+ if (SCM_EXACT_ZERO_P(arg1)) {
+ if (inexact) goto anormal;
+ else goto div_by_zero;
+ }
if (SCM_EXACT_ZERO_P(arg0)) SIMPLE_RETURN(arg0);
if (SCM_EXACT_ONE_P(arg1)) SIMPLE_RETURN(arg0);
if (compat) {
@@ -2038,7 +2047,10 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
}
if (SCM_BIGNUMP(arg0)) {
if (SCM_INTP(arg1)) {
- if (SCM_EXACT_ZERO_P(arg1)) goto anormal;
+ if (SCM_EXACT_ZERO_P(arg1)) {
+ if (inexact) goto anormal;
+ else goto div_by_zero;
+ }
if (SCM_EXACT_ONE_P(arg1)) SIMPLE_RETURN(arg0);
goto ratnum_return;
}
@@ -2061,7 +2073,10 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
}
if (SCM_RATNUMP(arg0)) {
if (SCM_INTP(arg1)) {
- if (SCM_EXACT_ZERO_P(arg1)) goto anormal;
+ if (SCM_EXACT_ZERO_P(arg1)) {
+ if (inexact) goto anormal;
+ else goto div_by_zero;
+ }
if (SCM_EXACT_ONE_P(arg1)) SIMPLE_RETURN(arg0);
arg1 = Scm_Mul(SCM_RATNUM_DENOM(arg0), arg1);
arg0 = SCM_RATNUM_NUMER(arg0);
@@ -2180,6 +2195,10 @@ scm_div(ScmObj arg0, ScmObj arg1, int inexact, int compat, int vmp)
if (inexact) return Scm_Inexact(r);
else return r;
}
+ div_by_zero:
+ {
+ Scm_Error("attempt to calculate a division by zero");
+ }
anormal:
{
int s = Scm_Sign(arg0);
diff --git a/test/number.scm b/test/number.scm
index bee2157..bf59d43 100644
--- a/test/number.scm
+++ b/test/number.scm
@@ -1211,6 +1211,32 @@
(test* "exact reciprocal" -5/6 (/ -6/5))
(test* "exact reciprocal" 7/4692297364841 (/ 4692297364841/7))
+;; avoid inlining
+(define (divide . args)
+ (apply / args))
+
+(define (divide. . args)
+ (apply /. args))
+
+(test* "division by zero" (test-error) (divide 0))
+(test* "division by zero" (test-error) (divide 0 0))
+(test* "division by zero" (test-error) (divide 3 0))
+(test* "division by zero" (test-error) (divide 1/2 0))
+(test* "division by zero" +inf.0 (divide 0.0))
+(test* "division by zero" #t (nan? (divide 0.0 0)))
+(test* "division by zero" #t (nan? (divide 0 0.0)))
+(test* "division by zero" #t (nan? (divide 0.0 0.0)))
+(test* "division by zero" +inf.0 (divide 0.5 0))
+
+(test* "division by zero" +inf.0 (divide. 0))
+(test* "division by zero" #t (nan? (divide. 0 0)))
+(test* "division by zero" +inf.0 (divide. 3 0))
+(test* "division by zero" +inf.0 (divide. 1/2 0))
+(test* "division by zero" #t (nan? (divide. 0.0 0)))
+(test* "division by zero" #t (nan? (divide. 0 0.0)))
+(test* "division by zero" #t (nan? (divide. 0.0 0.0)))
+(test* "division by zero" +inf.0 (divide. 0.5 0))
+
(define (almost=? x y)
(define (flonum=? x y)
(let ((ax (abs x)) (ay (abs y)))
- Shiro(2012/10/07 18:02:33 UTC): R5RSの「結果が正確数で表現できないときは 非正確数にcoerceしてよい」条項を適用してたんですが、R6RSでは陽にエラーであると 指定されてますから、こっちの方がいいですね。ついでに 1/0 も今まで +inf.0 に してたのをエラーにしました。(#i1/0 は依然として +inf.0 になります。)
(integer? +inf.0) の戻り値 (4a61d3)
leque(2012/07/20 09:57:36 UTC): (integer? +inf.0) と (integer? -inf.0) が #t を返しますが、 R6RS / SRFI-70 的には #f だと思います。
gosh> (integer? +inf.0) #t gosh> (rational? +inf.0) #f gosh> (real? +inf.0) #t
diff --git a/src/number.c b/src/number.c
index 05f965a..adce258 100644
--- a/src/number.c
+++ b/src/number.c
@@ -1296,6 +1296,7 @@ int Scm_IntegerP(ScmObj obj)
{
if (SCM_INTP(obj) || SCM_BIGNUMP(obj)) return TRUE;
if (SCM_RATNUMP(obj)) return FALSE; /* normalized ratnum never be integer */
+ if (Scm_InfiniteP(obj)) return FALSE;
if (SCM_FLONUMP(obj)) {
double d = SCM_FLONUM_VALUE(obj);
double f, i;
diff --git a/test/number.scm b/test/number.scm
index b5ad471..638d612 100644
--- a/test/number.scm
+++ b/test/number.scm
@@ -584,6 +584,9 @@
(test* "integer?" #f (integer? 3+4i))
(test* "integer?" #t (integer? 3+0i))
(test* "integer?" #f (integer? #f))
+(test* "integer?" #f (integer? +inf.0))
+(test* "integer?" #f (integer? -inf.0))
+(test* "integer?" #f (integer? +nan.0))
(test* "rational?" #t (rational? 0))
(test* "rational?" #t (rational? 85736847562938475634534245))
- Shiro(2012/07/21 10:28:12 UTC): Fixed. Mahalo.
SRFI-19 の閏秒テーブルの更新 (0.9.3.3)
leque(2012/07/07 14:28:32 UTC): 2012/07/01 の閏秒の分です
diff --git a/ext/srfi/srfi-19.scm b/ext/srfi/srfi-19.scm
index cf3a499..9fb36b0 100644
--- a/ext/srfi/srfi-19.scm
+++ b/ext/srfi/srfi-19.scm
@@ -110,7 +110,8 @@
;; note they go higher to lower, and end in 1972.
;; See srfi-19/read-tai.scm to update this list.
(define-constant tm:leap-second-table
- '((1230768000 . 34)
+ '((1341100800 . 35)
+ (1230768000 . 34)
(1136073600 . 33)
(915148800 . 32)
(867715200 . 31)
- Shiro(2012/07/07 16:25:14 UTC): まはろ〜
string-scan-rightの挙動がおかしい (0.9.3.3)
2012/06/27 13:04:32 UTC
gosh> (string-scan-right "ab" "cd") -1 gosh> (string-scan-right "abcd" "cd") -1 gosh> (string-scan-right "cdcd" "cd") #f
など
- Shiro(2012/06/27 15:13:49 UTC): ぎゃー。絵に描いたようなoff-by-oneバグでした。fixed (61254ca)
match-defineが動かない (~0.9.3.3)
rallentando?2012/06/10 13:40:38 UTC:初めましてですみません、見つけたので。(いつからなのか分かりませんが、少なくとも0.9.1でも動きませんでした。)
gosh> (use util.match) #<undef> gosh> (match-define (x . xs) (list 1 2)) *** ERROR: unbound variable: code Stack Trace: _______________________________________ gosh>
のようにmatch-defineが動きませんでした。 ソースを見てみると、
(define (gendefine pat exp match-expr)
(let* ((eb-errf (error-maker match-expr))
(x (bound (validate-pattern pat)))
(p (car x))
(bv (cadr x))
(bindings (caddr x))
(code (gensym))
(plist (list (list p code bv #f #f)))
(x (gensym))
(m (gen x '() plist (cdr eb-errf) (gensym)))
(gs (map (lambda (_) (gensym)) bv)))
(unreachable plist match-expr)
`(begin ,@(map (lambda (v) `(define ,v #f)) bv)
;;ここ
`(let ((,x ,exp)
(,code (lambda ,gs
,@(map (lambda (v g) `(set! ,v ,g)) bv gs)
(cond (#f #f))))
,@bindings
,@(car eb-errf))
,m))))
`(let ((,x ,exp)... の行頭の準クオート一個はずしたら動きました。
- Shiro(2012/10/22 22:53:22 UTC): Fixed.
部分継続の動作が怪しい (0.9.3.2)
Shiro(2012/05/26 09:55:25 UTC): lequeさんの指摘: https://twitter.com/dico_leque/status/204755081936125952
『shift/reset プログラミング入門』の A 正規形変換の例が Gauche だと attempt to return from a ghost continuation. で叱られるのはどうしてだろう。 Racket だと動く http://ideone.com/ub0UW
leque (2012/05/29 05:12:15 UTC): 別の例を探してみました。 Typed Printf via Delimited Continuations を Gauche で書いてみると、
(use gauche.partcont)
(define (sprintf format)
(reset (format)))
(define (fmt dir)
(shift k
(lambda (v)
(k (dir v)))))
(define s values)
((sprintf (lambda () (string-append "hello, " (fmt s)))) "world") ;; => "hello, world"
は値を返しますが、
;; "world" を返してほしい ((sprintf (lambda () (fmt s))) "world") ;; -> *** ERROR: attempt to return from a ghost continuation.
はエラーになります。
- Shiro(2012/07/21 11:43:21 UTC): 捕捉される部分継続が空の場合 (resetのスタックフレームから 何も積まれてない状態でshiftが呼ばれた場合) のハンドリングをしくじっていました。 Fixed (61f5d17).
iota に負数を与えたときの errorf のフォーマットがおかしい (0e669e)
cryks(2012/05/21 13:04:36 UTC): おそらく意図されているのは error だと思います。
gosh> (iota -1) *** ERROR: too many arguments for format string: "count must be nonnegative: "
diff --git a/src/liblist.scm b/src/liblist.scm
index 0f470a8..279aba9 100644
--- a/src/liblist.scm
+++ b/src/liblist.scm
@@ -221,7 +221,7 @@
(define (last lis) (car (last-pair lis))) ;srfi-1
(define (iota count :optional (start 0) (step 1)) ;srfi-1
- (when (< count 0) (errorf "count must be nonnegative: " count))
+ (when (< count 0) (error "count must be nonnegative: " count))
(if (and (exact? start) (exact? step))
(do ([c count (- c 1)]
[v (+ start (* (- count 1) step)) (- v step)]
- Shiro(2012/05/26 09:39:00 UTC): Fixed.
every / stream-every の戻り値(0e669e)
leque(2012/05/20 00:40:00 UTC): たぶん 0035eb の変更以降、 every にふたつ以上のリストを渡した場合に、最後の pred の呼び出しの戻り値でなく #t を返すようになっています。
gosh> (every string->number '("2"))
2
gosh> (every string->number '("2") '(10))
#t
パッチ: https://gist.github.com/2732942
stream-every の場合は、引数に渡したストリームの個数によらず常に真値(として引数のストリームのうち最初に空になったもの)が返ります。
gosh> (use util.stream)
#<undef>
gosh> (stream-every string->number (list->stream '("2")))
#<promise(stream) 0x10111d9e0 (forced)>
gosh> (stream-every string->number (list->stream '("2")) (list->stream '(10)))
#<promise(stream) 0x10111d520 (forced)>
こちらは特にドキュメントに何も書かれていないのですが、 SRFI 1 と同じ挙動の方がわかりやすいと思います。
パッチ: https://gist.github.com/2733012
- Shiro(2012/05/26 09:39:00 UTC): Fixed.
MacOSX 10.7.3でfork中にGCが起こると"thread_suspend failed"エラーで止まる [0.9.3.2]
koguro(2012/05/19 10:58:38 UTC): MacOSX 10.7.3で以下のプログラムを実行すると"thread_suspend failed"エラーで止まってしまいます。BoehmGC側の問題かと思いますが、GC_stop_worldでthread_suspendがKERN_SUCCESS以外の値を返した時にアボートするようなコードに変更されていて、ここで引っかかっているんだと思います。 再現プログラムは以下のとおりです。
;; err.scm
(receive (in out) (sys-pipe)
(if (= (sys-fork) 0)
(begin
(dotimes (i 1000)
(make-vector 10000))
(sys-exit 0))
(sys-wait)))
% gosh err.scm thread_suspend failed
なお、Linux (Linux ubuntu64 3.0.0-13-generic #22-Ubuntu SMP Wed Nov 2 13:27:26 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux) とFreeBSD (FreeBSD freebsd64.koguro.net 8.1-RELEASE FreeBSD 8.1-RELEASE #0)で試したところ正常に動作しました。
- Shiro(2012/05/19 11:10:06 UTC): これが出るってことは、既に複数のスレッドが走ってるってことかな。
thread_suspend()の呼び出しは自スレッドは除外してますよね。暗黙にスレッドが作られてる
とすれば、確かにfork()した子プロセスでは自スレッド以外はいなくなってるので、failしますよねえ。gc/configure.acの次の箇所を変えてmaintainer-clean + ./DIST gen からやり直すとどうなりますか。
diff --git a/gc/configure.ac b/gc/configure.ac index f422e4d..f691f52 100644 --- a/gc/configure.ac +++ b/gc/configure.ac @@ -660,7 +660,7 @@ AC_DEFINE(LARGE_CONFIG) dnl [SK] this may also needed to use sys-fork safely in multithreaded dnl Gauche, but this seems to hang on some platforms. So I don't put dnl it in by default. -dnl AC_DEFINE(HANDLE_FORK) +AC_DEFINE(HANDLE_FORK) AC_SUBST(UNWINDLIBS)
- koguro(2012/05/19 11:43:49 UTC): AC_DEFINE(HANDLE_FORK)をつけても、同じく thread_suspend failed で止まりました。
- Shiro(2012/05/26 11:02:44 UTC): gcを7.2bに更新してみました。スレッドまわりに 結構手が入ってるようですが、どうでしょうか。
- koguro(2012/05/26 23:03:44 UTC): 9c6e85 にして --enable-handle-fork をつけると正常に動作しました (--enable-handle-forkなしだと、結果は同じく thread_suspended failed で止まりました)。ちなみにどちらのオプションでもmake checkは通っています。
- Shiro(2012/05/27 19:17:43 UTC): Mahalo。ENABLE_FORKをデフォルトでonにしてしばらく 様子を見てみようかな。前にどのプラットフォームで問題が出たのか忘れてしまった。
- Shiro(2012/05/28 00:12:35 UTC): というわけでHANDLE_FORKをonにしてあります(7544e34)。 他のプラットフォームでどうなるか様子見。
- Shiro(2012/05/28 11:12:24 UTC): なんかOSX 10.7.4で問題が出たのでHANDLE_FORKは undefinedに戻しました。gcを7.3alpha2にした方が良いかなあ。
--enable-multibyte=utf8 以外のエンコーディングでconfigureするとドキュメントのビルドに失敗する [0.9.3]
Shiro(2012/05/11 18:10:04 UTC): out-of-tree buildのサポートをした時にエンバグしてました。 コンパイルで引っかかると不便なので、新たなtarballを0.9.3.2としてリリースしました。
ビルド時の問題以外はほぼ変わってないので、utf-8でコンパイルする分には急いでアップデート する必要はありません。