052: CompositDict に引数として与えられた辞書を格納できていない

↑up

概要

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 (Sun)

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)

これで、治った。