Haskell: Pugs 6.0.5をビルドするためのパッチ

Pugs 6.0.5(リビジョン29)をビルドするためのパッチを作ってみた。

ただし、このパッチは完全じゃない。makeはできるけれども、make testが通らない。本当に単純なexpression、例えば「1+2」はうまく評価できるけれども、サブルーチンが絡んでくるとうまく評価できない。原因はよくわかっていない。(原因がわかった。追記を参照。) このパッチは、インポートによる関数の衝突(特にData.SetとData.List)が発生しないようにしただけなので、それがまずいのかもしれない。

それでも試したい方は、

を参考にしてパッチを当ててみるとよいかもしれない。

ビルドしてできたpugsインタプリタを実行すると以下のような感じで動作する。このバージョンでは、評価の過程がダンプされるのでちょっと楽しい。

% ./pugs 
.=====. __  __  ____   ___    _________________________________________
||   || ||  || ||  || ||__'   Pugs 6: Based on the Perl 6 Synopses     
||====' ||__|| ||__||  __||   Copyright 2005 by Autrijus Tang
||      `===='  ___|| `==='   World Wide Web: http://autrijus.org/pugs 
||             `===='         Report bugs to: autrijus@autrijus.org    
==                  Version:  =========================================

Welcome to Pugs -- Perl6 User's Golfing System
Type :h for help

pugs> 1+2
*** Evl: Syn ";" {{ App "&infix:+" [Val (VInt 1),Val (VInt 2)] [] }}
***  Evl: App "&infix:+" [Val (VInt 1),Val (VInt 2)] []
***   Evl: Syn "[]" {{ Syn "," {{  }}; (0, ...) }}
***    Evl: Syn "," {{  }}
***    Ret: ()
***   Ret: ()
***  Ret: 3
*** Ret: 3
3
pugs> "hello, " ~ "world"
*** Evl: Syn ";" {{ App "&infix:~" [Val (VStr "hello, "),Val (VStr "world")] [] }}
***  Evl: App "&infix:~" [Val (VStr "hello, "),Val (VStr "world")] []
***   Evl: Syn "[]" {{ Syn "," {{  }}; (0, ...) }}
***    Evl: Syn "," {{  }}
***    Ret: ()
***   Ret: ()
***  Ret: "hello, world"
*** Ret: "hello, world"
"hello, world"

以下独り言。

Pugs 6.0.5のコードは、6.0.0のコードと比べて理解するのが非常に難しい。
特に、

  • 継続(continuation)
  • Reader Monad
  • Monad Transformer

の辺り。

これらがわからないと読めそうにない。

Parser.hsやEval.hsも初期バージョンと比べると断然進化している。

Evalの型が

type Eval x = ContT Val (ReaderT Env IO) x

だと言われても、今は全然ピンと来ない。

でも、上で挙げた3つの概念と実際のコードとの対応が理解できれば、ひとまず山は越えられそうな予感。

追記 (2006/04/14 08:40)

make testが通らない訳がわかった。Pugs 6.0.5(リビジョン29)では、後で定義するサブルーチンを他のサブルーチンから呼び出すとまずいらしい。

この原因は、Pugsのコミットログがヒントになってわかった。以下のような記述が残っていたので、気になって差分を見てみた。

r30 | autrijus | 2005-02-16 15:24:13 +0900 (水, 16  2月 2005) | 1 line

* bandaid to cure lexical scope bugs

単に呼び出し順序を変えただけのようだ。この変更を適用すると、無事make testが通るようになった。

Index: t/01basic.t
===================================================================
--- t/01basic.t (revision 29)
+++ t/01basic.t (revision 30)
@@ -11,9 +11,9 @@
 
 open PUGS, "| $pugs" or die "Cannot pipe out to $pugs: $!";
 print PUGS << '.';
-    sub cool { fine($_) ~ " # We've got " ~ toys };
     sub fine { "ok " ~ $_ };
     sub toys { "fun and games!\n" };
+    sub cool { fine($_) ~ " # We've got " ~ toys };
     cool 2
 .
 close PUGS;