# 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) $$} これで、治った。