# 085: oddInt.hs がランタイムで abend [↑up](bunny_notes) - issued: 2020-05-18 - 分類: A サンプルコードが fail - status: Closed (2020-05-27) ## 概要 lib/Prelude.hs に追加した、even, odd は、内部であやまって Num t => t が Integer に特殊化されてしまっていて、Int の引数をあたえると abend する。 $$
{ (Prelude.even :: ([Prelude.Integral t1408] :=> (t1408 -> Prelude.Bool))) = \(Prelude.even.DARG0 :: Ä) -> \(_Prelude.even.U1 :: ([Prelude.Integral t1402] :=> t1402)) -> ((((Prelude.== :: ([Prelude.Eq t1404] :=> (t1404 -> (t1404 -> Prelude.Bool)))) ${Prelude.Integer Prelude.Eq}) ((((Prelude.rem :: ([Prelude.Integral t1405] :=> (t1405 -> (t1405 -> t1405)))) (Prelude.even.DARG0 :: Å)) (_Prelude.even.U1 :: ([Prelude.Integral t1402] :=> t1402))) (((Prelude.fromInteger :: ([Prelude.Num t1406] :=> (Prelude.Integer -> t1406))) (Prelude.even.DARG0 :: Å)) (2 :: Prelude.Integer)))) (((Prelude.fromInteger :: ([Prelude.Num t1407] :=> (Prelude.Integer -> t1407))) (Prelude.even.DARG0 :: Å)) (0 :: Prelude.Integer))) $$} ## 調査ログ ## 2020-05-20 gcd, lcm でも同じ問題が発現。gcdlcm2.hs ## 2020-05-21 ### oddInt については原因判明 概要にあげた core では、Prelude.Eq t1404 にあたる型変数が Prelude.Integral t1408 に一致せず、lookupDict が Nothing を返していた。(その結果 defaulting が実施され Integer に) 原因は、Eq が Integral に一致せず、Integral の supers のどれにも一致しなかったため。 Eq は Integral の super の super なので、再帰的に検査しなければならなかった。 $${ @@ -197,10 +197,10 @@ lookupDictArg (c, y) = do ce <- getCe let d = zip (map (\((IsIn i t), _) -> (i, apply s t)) pss) [(0::Int)..] lookupDict (k, tv) (((c, tv'), i):d') - | tv == tv' && (k == c || k `elem` super ce c) = Just i + | tv == tv' && c `isin` k = Just i | otherwise = lookupDict (k, tv) d' lookupDict _ [] = Nothing - + c1 `isin` c2 = (c1 == c2)|| (or $ map (`isin` c2) (super ce c1)) ret = case lookupDict (c, TVar y) d of Nothing -> Nothing Just j -> let (_, n) = pss !! j $$} また、CodeGen も同様に、super の super も処理する必要があった。 $${ --- a/compiler/src/CodeGen.hs +++ b/compiler/src/CodeGen.hs @@ -8,7 +8,7 @@ import Symbol import Typing (ClassEnv (..), super) import Control.Monad.State.Strict -import Data.List (find, intercalate) +import Data.List (find, intercalate, nub) import Data.List.Split (splitOn) import qualified Data.Map as Map import Data.Maybe (fromJust, fromMaybe) @@ -486,7 +486,8 @@ emitInsts dest dicts ((qin, qcn):ctab) ce = do let ms = ddMethods $ fromJust $ find ((== qcn). ddId) dicts msM = map mangle ms pdname = cls2dictNameM qcn - supers = super ce qcn + f c = c : concatMap f (super ce c) + supers = nub $ concatMap f (super ce qcn) sdname = map cls2dictNameM supers dname = cls2dictNameM $ qin ++ "@" ++ qcn mname = modname qin $$} これによって、oddInt.hs は通るようになった ⇒ sample220.hs だが、gcdlcm2.hs はまだダメ。こちらも、lookupDict が Nothing を返しているのだが、 クラスではなく tv が不一致であるらしく、原因は別のところにあるようだ。 ## 2020-05-27 [092](bissue092) 対処により、gcdlcm2.hs も通るようになった。 - gcdlcm2.hs -> sample228.hs