sigdoc1.hs をコンパイルすると、Variable not found: Main.l0.l0.s となって失敗:
$ ./test-compile.sh testcases/sigdoc1.hs source file: testcases/sigdoc1.hs dst dir: /sigdoc1 doCompile ... done. implicitPrelude ... done. doCompile ... bunnyc: Variable not found: Main.l0.l0.s , fromList [] , [fromList []] CallStack (from HasCallStack): error, called at src/CodeGen.hs:282:33 in main:CodeGen
CodeGen でコケているので、型推論は通っている。 途中の中間言語をダンプしてみてみる。
まずは、sigdoc1.hs の場合:
$ ./test-compile.sh --ddump-core testcases/sigdoc1.hs basename: unrecognized option '--ddump-core' Try 'basename --help' for more information. source file: --ddump-core dst dir: / doCompile ... done. implicitPrelude ... done. doCompile ... ---- ddumpCore ---- (Main.main :: (Prelude.IO ())) = let in ((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) (Main.l0.l0.s :: [Prelude.Char])) bunnyc: Variable not found: Main.l0.l0.s , fromList [] , [fromList []] CallStack (from HasCallStack): error, called at src/CodeGen.hs:282:33 in main:CodeGen
一方、sigdoc1b.hs (これはコンパイル通る)の場合は以下:
$ ./test-compile.sh --ddump-core testcases/sigdoc1b.hs basename: unrecognized option '--ddump-core' Try 'basename --help' for more information. source file: --ddump-core dst dir: / doCompile ... done. implicitPrelude ... done. doCompile ... ---- ddumpCore ---- (Main.s :: [Prelude.Char]) = "Hello, world!" (Main.main :: (Prelude.IO ())) = ((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) (Main.s :: [Prelude.Char])) done.
renDecl の動作を、Level 管理周りや、そもそも、Absyn の仕様も含めて、きちんと確認しないといけない。
前日の --ddump-core は比べるものがちがっていた。 sigdoc1.hs は以下の通り:
$ cat testcases/sigdoc1.hs main = putStrLn s where s :: [Char] s = "Hello, world!"
これをコンパイルすると、昨日示したとおり、core の時点で s の定義がぬけおちている。
(Main.main :: (Prelude.IO ())) = let in ((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) (Main.l0.l0.s :: [Prelude.Char]))
では、sigdoc1.hs から s の型宣言だけ取り除いたもの:
main = putStrLn s where s = "Hello, world!"
これをコンパイルしたときの core は次のとおり、
(Main.main :: (Prelude.IO ())) = let (Main.l0.l0.s :: [Prelude.Char]) = "Hello, world!" in ((Prim.putStrLn :: ([Prelude.Char] -> (Prelude.IO ()))) (Main.l0.l0.s :: [Prelude.Char]))
どこで抜け落ちたのかと思い、renExp (A.LetExp ds e) に以下の通り、trace を仕掛けて比較:
renExp (A.LetExp ds e) = do enterNewLevel (ds', _, _) <- scanDecls ds tbs <- renDecls ds' e' <- renExp e exitLevel let bgs = toBg tbs trace (show bgs) $ return (Let (head bgs) e') -- TODO: (head bgs) is temporary
どうも、この時点では正しそう。trCore が被疑個所なのでは。
trCore の該当箇所。Explicit Binding を捨てている!
trExpr2 (Ty.Let bg e) = do trace (show (Ty.Let bg e)) $ return () pushBind ci <- getCi let (_, iss) = bg is = concat iss vdefs = dsgIs [] is ci transVdefs vdefs b' <- popBind e' <- trExpr2 e return $ Let b' e'
参考まで、上のように仕掛けた trace による表示を以下に示す:
Explicit Binding を捨てないようにし、また、dsgIs は Implicit 以外の Bindings も扱うのだからと、名前を dsgBs に変更…
trExpr2 (Ty.Let bg e) = do pushBind ci <- getCi let (es, iss) = bg es' = map (\(n, _, alts) -> (n, alts)) es is = concat iss vdefs = dsgBs [] (es' ++ is) ci transVdefs vdefs b' <- popBind e' <- trExpr2 e return $ Let b' e'
したら、Desuger.hs では、すでに同様の問題に対処済だったことが判明。
dsgModule :: Id -> Ty.Program -> [Ty.Assump] -> ConstructorInfo -> Module dsgModule modident bgs as ci = let [(es, iss)] = bgs is = concat iss es' = map (\(n, _, alts) -> (n, alts)) es vdefs = dsgBs [] (es' ++ is) ci b = translateVdefs as vdefs ci in Core.Module modident [b]
なぜ、そのとき一緒に直さなかったのか…。