以下のようなプログラム (litpatternb.hs) をコンパイルすると、Parse Error となる。
f x = case x of
0 -> "zero"
_ -> "non-zero"
main = do putStrLn $ f 1
putStrLn $ f 0
つぎのように変換してやればいい(以下のプログラムは現状でも通る)。
f x = case x of
x | x == 0 -> "zero"
_ -> "non-zero"
main = do putStrLn $ f 1
putStrLn $ f 0
変換に際して、すこし気になったので、x | x == a -> hoge が複数生じるケースを追加 (litpetternc2.hs)
f x = case x of
x | x == 0 -> "zero"
x | x == 1 -> "one"
_ -> "other"
main = do print $ f 0
print $ f 1
print $ f 2
これがちゃんと通るので、大丈夫そう。
だが、現状のエラーは、この式変換以前に、Parse Error になっている。Parser.y をみてみなければ。
とりあえずコンパイルしてみる。
$ bunny tcompile litpatternb.hs /home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/litpatternb --xno-implicit-prelude /home/unno/bunny/0.9.0/lib/Prelude.hs /home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/litpatternb --xlibrary-path /home/unno/bunny/0.9.0/lib -v litpatternb.hs implicitPrelude ... done. Error: parseError: TInteger (0,AlexPn 24 2 3)
全件確認シリーズ:
unno@unno-FMVD70GN7G ~/work/bissues/084
$ cat litpatternb.hs
f x = case x of
0 -> "zero"
_ -> "non-zero"
main = do putStrLn $ f 1
putStrLn $ f 0
unno@unno-FMVD70GN7G ~/work/bissues/084
$ runhaskell litpatternb.hs
non-zero
zero
unno@unno-FMVD70GN7G ~/work/bissues/084
$ ~/prj/bunny/compiler/bin/bunny tcompile litpatternb.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib -v litpatternb.hs
implicitPrelude ... done.
Error: parseError: TInteger (0,AlexPn 24 2 3)
これと似てるが、リテラルじゃなくてリストにマッチさせるようなのもあって、 そちらも現状は parse error:
unno@unno-FMVD70GN7G ~/work/bissues/084
$ cat litpatternbX.hs
f x = case x of
'X' -> "X"
_ -> "not X"
main = do putStrLn $ f 'X'
putStrLn $ f 'Y'
unno@unno-FMVD70GN7G ~/work/bissues/084
$ runhaskell litpatternbX.hs
X
not X
unno@unno-FMVD70GN7G ~/work/bissues/084
$ ~/prj/bunny/compiler/bin/bunny tcompile litpatternbX.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternbX --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternbX --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib -v litpatternbX.hs
implicitPrelude ... done.
Error: parseError: TChar ('X',AlexPn 24 2 3)
文法をみなおしても、これが文法エラーになるようには見えない。 また、GHC の Parser.y.source の対応する部分と見比べても、とくに変なところがない。
もしかして、文法エラー以外にも (semantic action で例外をなげるなどで) parseError になる場合があるのかというめで Parser.y をみると、vcurly の対応がとれない場合なんかにそうなるみたい。
では、というので、レイアウト規則を使わないように libpatternb.hs を書き換えてみたら、通った!
unno@unno-FMVD70GN7G ~/work/bissues/084
$ cat litpatternb_curly.hs
f x = case x of { 0 -> "zero"; _ -> "non-zero" }
main = do putStrLn $ f 1
putStrLn $ f 0
unno@unno-FMVD70GN7G ~/work/bissues/084
$ ~/prj/bunny/compiler/bin/bunny testrun litpatternb_curly.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb_curly --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb_curly --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib litpatternb_curly.hs
non-zero
zero
被疑箇所はレイアウト規則の処理だったもよう。
unno@unno-FMVD70GN7G ~/work/bissues/084
$ cat litpatternb3.hs
f x = case x of
0.0 -> "zero"
_ -> "non-zero"
main = do putStrLn $ f (1.0::Double)
putStrLn $ f (0.0::Float)
$ runhaskell litpatternb3.hs
non-zero
zero
unno@unno-FMVD70GN7G ~/work/bissues/084
$ ghci litpatternb3.hs
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( litpatternb3.hs, interpreted )
Ok, one module loaded.
*Main> :t f
f :: (Eq a, Fractional a) => a -> [Char]
*Main> :q
Leaving GHCi.
unno@unno-FMVD70GN7G ~/work/bissues/084
$ ~/prj/bunny/compiler/bin/bunny tcompile --ddump-assump litpatternb3.hs |& less
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb3 --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb3 --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib -v --ddump-assump litpatternb3.hs
implicitPrelude ... done.
Error: parseError: TFloat (0.0,AlexPn 24 2 3)
TFloat も act_token を介すように変更しなくてはいけない。以下のとおり変更:
$ git diff
diff --git a/compiler/src/Lexer.x b/compiler/src/Lexer.x
index adfb4b0..231f96c 100644
--- a/compiler/src/Lexer.x
+++ b/compiler/src/Lexer.x
@@ -533,7 +533,7 @@ act_integer (pos, _, _, s) len = act_token (TInteger (i, pos)) pos
i = read $ take len s
act_float :: AlexAction Token
-act_float (pos, _, _, s) len = do unFlags; return $ TFloat (x, pos)
+act_float (pos, _, _, s) len = do act_token (TFloat (x, pos)) pos
where
x = read $ take len s
}
コンパイル通るようになり、Main.f の型もただしい(GHC のときと同じ)ようだ:
/home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb3 --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb3 --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib -v --ddump-assump litpatternb3.hs implicitPrelude ... done. doCompile ... Debugging dump of assumptions (results of the type inference). #overloaded# :: (a -> ([Prelude.Char] -> b)) Main.f :: Forall [Star] ([Prelude.Fractional a] :=> (a -> [Prelude.Char]))
実行結果:
$ ~/prj/bunny/compiler/bin/bunny testrun litpatternb3.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb3 --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/litpatternb3 --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib litpatternb3.hs non-zero zero
これで、いちおう、本 issue はクローズかな。テストにいくつか加えよう。sample334-337