# 052: CompositDict に引数として与えられた辞書を格納できていない [↑up](bunny_notes) - issued: 2020-05-02 - 分類: A サンプルコードが fail - status: Closed (2020-05-03) ## 概要 Defaulting がひどいのを直した結果 showsPrec など実装できるかためしてみたところ、 型推論の問題は起こらなかった(これは期待した通り)が、ランタイムで以下のようなエラー: $$
{
javac -J-Duser.language=en -cp "../../brt/src$s$d" $target
g2/Prelude.java:3536: error: cannot find symbol
      Expr t5 = Prelude.mk_91__93__37_I_46_showsPrec_46_DARG0();
                       ^
  symbol:   method mk_91__93__37_I_46_showsPrec_46_DARG0()
  location: class Prelude
g2/Prelude.java:3659: error: cannot find symbol
      Expr t5 = Prelude.mk_40__44__41__37_I_46_showsPrec_46_DARG0();
                       ^
  symbol:   method mk_40__44__41__37_I_46_showsPrec_46_DARG0()
  location: class Prelude
g2/Prelude.java:3661: error: cannot find symbol
      Expr t6 = Prelude.mk_40__44__41__37_I_46_showsPrec_46_DARG1();
                       ^
  symbol:   method mk_40__44__41__37_I_46_showsPrec_46_DARG1()
  location: class Prelude
g2/Prelude.java:4093: error: cannot find symbol
      Expr t10 = Prelude.mk_91__93__37_I_46_showList_46_DARG0();
                        ^
  symbol:   method mk_91__93__37_I_46_showList_46_DARG0()
  location: class Prelude
g2/Prelude.java:4106: error: cannot find symbol
      Expr t22 = Prelude.mk_91__93__37_I_46_showList_46_DARG0();
                        ^
  symbol:   method mk_91__93__37_I_46_showList_46_DARG0()
  location: class Prelude
g2/Prelude.java:4283: error: cannot find symbol
      Expr t10 = Prelude.mk_40__44__41__37_I_46_showList_46_DARG0();
                        ^
  symbol:   method mk_40__44__41__37_I_46_showList_46_DARG0()
  location: class Prelude
g2/Prelude.java:4285: error: cannot find symbol
      Expr t11 = Prelude.mk_40__44__41__37_I_46_showList_46_DARG1();
                        ^
  symbol:   method mk_40__44__41__37_I_46_showList_46_DARG1()
  location: class Prelude
g2/Prelude.java:4298: error: cannot find symbol
      Expr t23 = Prelude.mk_40__44__41__37_I_46_showList_46_DARG0();
                        ^
  symbol:   method mk_40__44__41__37_I_46_showList_46_DARG0()
  location: class Prelude
g2/Prelude.java:4300: error: cannot find symbol
      Expr t24 = Prelude.mk_40__44__41__37_I_46_showList_46_DARG1();
                        ^
  symbol:   method mk_40__44__41__37_I_46_showList_46_DARG1()
  location: class Prelude
9 errors
$$}

例えば Prelude.[]%I.showsPrec は、自分が受け取った辞書を CompositDict
にして Prelude.show に渡す。該当部の Core は以下のようになっている:

$$
{
(Prelude.[]%I.showsPrec :: ([Prelude.Show t267] :=> (Prelude.Int -> ([t267] -> ([Prelude.Char] -> [Prelude.Char]))))) =
    \(Prelude.[]%I.showsPrec.DARG0 :: Ä) ->
        \(_Prelude.[]%I.showsPrec.U1 :: ([Prelude.Show t264] :=> Prelude.Int)) (_Prelude.[]%I.showsPrec.U2 :: ([Prelude.Show t264] :=> [t264])) (_Prelude.[]%I.showsPrec.U3 :: ([Prelude.Show t264] :=> [Prelude.Char])) ->
            (((Prelude.++ :: ([t265] -> ([t265] -> [t265]))) 
                (((Prelude.show :: ([Prelude.Show t266] :=> (t266 -> [Prelude.Char]))) 
                    (CompositDict ${Prelude.[] Prelude.Show} [(Prelude.[]%I.showsPrec.DARG0 :: Å)])) 
                  (_Prelude.[]%I.showsPrec.U2 :: ([Prelude.Show t264] :=> [t264])))) 
              (_Prelude.[]%I.showsPrec.U3 :: ([Prelude.Show t264] :=> [Prelude.Char])))
$$}

この辞書から変数として渡された辞書を取り出すところがまずい:

$$
{
    public static class LAM310 implements LambdaForm {
     public int arity(){ return 3; }
     public Expr call(AtomExpr[] args){
      Expr t0 = Prelude.mk_43__43_();
      Expr t1 = Prelude.mkshow();
      Expr t2 = (Expr) new AtomExpr(new Dict(new Dict_36_Prelude_46__91__93__64_Prelude_46_Show()));
      AtomExpr t3 = (AtomExpr) t2;
      AtomExpr[] t4 = new AtomExpr[1];
      Expr t5 = Prelude.mk_91__93__37_I_46_showsPrec_46_DARG0();
      t4[0] = (AtomExpr) t5;
      Expr t6 = (Expr) new AtomExpr(new CompositDict(t3, t4));
      Expr t7 = RTLib.mkApp(t1, t6);
      Expr t8 = args[1];
      Expr t9 = RTLib.mkApp(t7, t8);
      Expr t10 = RTLib.mkApp(t0, t9);
      Expr t11 = args[2];
      Expr t12 = RTLib.mkApp(t10, t11);
      return t12;
     }
    }

    public static class LAM309 implements LambdaForm {
     public int arity(){ return 1; }
     public Expr call(AtomExpr[] args){
      Expr t0 = RTLib.mkFun(new LAM310());
      return t0;
     }
    }

    public static Expr mk_91__93__37_I_46_showsPrec(){
      Expr t0 = RTLib.mkFun(new LAM309());
      return t0;
    }
$$}

${Prelude.mk_91__93__37_I_46_showsPrec_46_DARG0()}
のようにスタティックな辞書生成関数(そんなものは存在しない)を呼び出すのでなく、
args を参照するようなコードを出力すべき。

おそらく、CompositDict に引数がわたされるようなケースはダメなので、
それを再現する小さなテストケースをつくって調査したい。(lib/Prelude でやるのはしんどい)

### 2020-05-03

CodeGen で、変数参照に対応するコードを出力している部分に trace を
仕込んで、なぜ args[0] へ変換されていないのか調べてみた。

$$
{
genAtomExpr :: Expr -> GEN Int
genAtomExpr (AtomExpr (VarAtom (TermVar n)))
  | n == "Prim.:"        = emit "RTLib.cons"
  | n == "Prim.[]"       = emit "RTLib.nil"
  | otherwise            = do
    st <- get
    let h = env st
        v = fromMaybe (refTopLevel n) (Map.lookup n h)
    trace (show (n, h)) $ return ()
    emit v
  where
    emit s = do
      i <- nexti
      appendCode $ "Expr t" ++ show i ++ " = " ++ s ++ ";"
      return i
$$}

その該当部分が以下:

$$
{
("Prelude.[]%I.showsPrec.DARG0",fromList [("_Prelude.[]%I.showsPrec.U1","args[0]"),("_Prelude.[]%I.showsPrec.U2","args[1]"),("_Prelude.[]%I.showsPrec.U3","args[2]")])
$$}

うーん。${\${darg0} u1 u2 u3 -> body} という4引数の1つの lambda
ではなく、${\${darg0} u1 u2 u3 -> (\u1' u2' u3' -> body) u1 u2 u3} 
みたいな変換になってんのかな。

STG.fv が、CompositDict 中の変数をとらえていないのが問題のようにも思える。

⇒ STG.fv を以下のように修正:

$$
{
-fv (AtomExpr (VarAtom (CompositDict _ _))) = []
+fv (AtomExpr (VarAtom (CompositDict e es))) = nub (fv e ++ concatMap fv es)
$$}

これで、治った。