# 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]
$$}
なぜ、そのとき一緒に直さなかったのか…。