# 010: sigdoc1.hs で variable not found [↑up](bunny_notes) - issued: 2020-04-09 - 分類: A サンプルコードが fail - status: Closed (2020-04-10) ## 現象 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 $$} ## 調査ログ ### 2020-04-09 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 の仕様も含めて、きちんと確認しないといけない。 ### 2020-04-10 前日の --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 $$} - 型シグネチャなし: ${[([],[[("Main.l0.l0.s",[([],Lit (LitStr "Hello, world!"))])]])]} - 型シグネチャあり: $ {[([("Main.l0.l0.s",Forall [] ([] :=> TAp (TCon (Tycon "[]" (Kfun Star Star))) (TCon (Tycon "Prelude.Char" Star))),[([],Lit (LitStr "Hello, world!"))])],[])]} どうも、この時点では正しそう。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 による表示を以下に示す: - シグネチャなし: ${Let ([],[[("Main.l0.l0.s",[([],Lit (LitStr "Hello, world!"))])]]) (Ap (Var "Prim.putStrLn") (Var "Main.l0.l0.s"))} - シグネチャあり: $ {Let ([("Main.l0.l0.s",Forall [] ([] :=> TAp (TCon (Tycon "[]" (Kfun Star Star))) (TCon (Tycon "Prelude.Char" Star))),[([],Lit (LitStr "Hello, world!"))])],[]) (Ap (Var "Prim.putStrLn") (Var "Main.l0.l0.s"))} ### 解決 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] $$} なぜ、そのとき一緒に直さなかったのか…。