以下のようなプログラム (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