084: litpatternb.hs で parseError: TInteger (0,AlexPn 24 2 3)

↑up

概要

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

調査ログ

2020-10-26 (Mon)

変換に際して、すこし気になったので、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 をみてみなければ。

2020-12-28 (Mon)

とりあえずコンパイルしてみる。

$ 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)

2021-10-24 (Sun)

全件確認シリーズ:

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)

2021-11-03 (Wed)

文法をみなおしても、これが文法エラーになるようには見えない。 また、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

被疑箇所はレイアウト規則の処理だったもよう。

2021-11-06 (Sat)

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