-- -- (c) Susumu Katayama -- \begin{code} {-# OPTIONS -fglasgow-exts -cpp #-} module MagicHaskeller.ReadTHType(thTypeToType, typeToTHType, showTypeName, plainTV, unPlainTV) where import MagicHaskeller.Types as Types import MagicHaskeller.TyConLib import Language.Haskell.TH as TH import Data.Array((!), inRange, bounds) import Data.Char(ord,chr) import Data.List(nub) import Data.Map(lookup) showTypeName = TH.nameBase -- Use the unqualified name to avoid confusion because Data.Typeable.tyConString shows the unqualified name for types defined in the Standard Hierarchical Library (though the qualified name is shown when Typeable is derived). -- showTypeName = show -- maybe in future, when TypeRep can be shown qualified. -- MyDynamicでしか使われていないので,ForallTは単に無視する.PolyDynamicのチェックがちょっと緩くなるだけ. thTypeToType :: TyConLib -> TH.Type -> Types.Type thTypeToType tcl t = normalize $ thTypeToType' tcl t thTypeToType' tcl (ForallT _ [] t) = thTypeToType' tcl t thTypeToType' tcl (ForallT _ (_:_) t) = error "Type classes are not supported yet." thTypeToType' tcl (TupleT n) = TC (tuple tcl n) thTypeToType' tcl ListT = TC (list tcl) -- thTypeToType' tcl (HsTyFun ht0 ht1) -- = thTypeToType' tcl ht0 :-> thTypeToType' tcl ht1 thTypeToType' tcl (AppT (AppT ArrowT ht0) ht1) = thTypeToType' tcl ht0 :-> thTypeToType' tcl ht1 thTypeToType' tcl (AppT (AppT (ConT name) ht0) ht1) | nameBase name == "(->)" = thTypeToType' tcl ht0 :> thTypeToType' tcl ht1 thTypeToType' tcl (AppT ht0 ht1) = TA (thTypeToType' tcl ht0) (thTypeToType' tcl ht1) thTypeToType' (fm,_) (ConT name) = let nstr = showTypeName name in case Data.Map.lookup nstr fm of Nothing -> TC $ (-1 - bakaHash nstr) -- error "nameToTyCon: unknown TyCon" Just c -> TC c {- この辺は単なるコメントアウトでいいんだっけ? thTypeToType' tcl (HsTyCon (Special HsUnitCon)) = TC (unit tcl) thTypeToType' tcl (HsTyCon (Special HsListCon)) = TC (list tcl) -} thTypeToType' _ ArrowT = error "Partially applied (->)." thTypeToType' _ (VarT name) = nameToVarType name -- thTypeToType' _ hst = error ("thTypeToType': "++show hst) nameToVarType name = strToVarType (showTypeName name) {- tcKindを廃止するので.ま,tcKindがなくてもhigher-order kindでなければトップレベルのkindから推論できるし. -- copied from svn/MagicHaskeller/memodeb/RandomFilter.hs typeToTHType :: TyConLib -> Types.Type -> TH.Type typeToTHType tcl ty = TH.ForallT (map tvToName $ tyvars ty) [] (typeToTHType' tcl ty) typeToTHType' (_,ar) (TC tc) | tcid >= 0 = TH.ConT (TH.mkName $ fst ((ar ! tcKind tc) !! tcid)) where tcid = tcID tc typeToTHType' tcl (TV tv) = TH.VarT $ tvToName tv typeToTHType' tcl (TA t0 t1) = TH.AppT (typeToTHType' tcl t0) (typeToTHType' tcl t1) typeToTHType' tcl (t0:->t1) = TH.AppT (TH.AppT TH.ArrowT (typeToTHType' tcl t0)) (typeToTHType' tcl t1) typeToTHType' tcl (t0:> t1) = TH.AppT (TH.AppT sectionedArrow (typeToTHType' tcl t0)) (typeToTHType' tcl t1) tvToName = TH.mkName . return . chr . (+ ord 'a') . tvID -} typeToTHType :: TyConLib -> Types.Type -> TH.Type typeToTHType tcl ty = (case tyvars ty of [] -> id tvs -> TH.ForallT (map (plainTV . tvToName) $ nub tvs) []) (typeToTHType' tcl 0 ty) typeToTHType' (_,ar) k (TC tc) | tc >= 0 = if name == "[]" then ListT else TH.ConT (TH.mkName name) where name = if inRange (bounds ar) k then fst ((ar ! k) !! tc) else 'K':shows k ('I':show tc) -- useful with defaultTCL typeToTHType' tcl _ (TV tv) = TH.VarT $ tvToName tv typeToTHType' tcl k (TA t0 t1) = TH.AppT (typeToTHType' tcl (k+1) t0) (typeToTHType' tcl 0 t1) typeToTHType' tcl 0 (t0:->t1) = TH.AppT (TH.AppT TH.ArrowT (typeToTHType' tcl 0 t0)) (typeToTHType' tcl 0 t1) typeToTHType' tcl 0 (t0:> t1) = TH.AppT (TH.AppT sectionedArrow (typeToTHType' tcl 0 t0)) (typeToTHType' tcl 0 t1) -- tvToName = TH.mkName . return . chr . (+ ord 'a') -- Maybe this should be dealt with by the version number of template-haskell, but how can I tell the number in the source code? #if __GLASGOW_HASKELL__<=610 plainTV = id unPlainTV = id #else plainTV = PlainTV unPlainTV (PlainTV v) = v #endif tvToName n = TH.mkName ('t':show n) -- secionedArrow = TH.ConT ''(->) -- 多分こっちでもOK sectionedArrow = TH.ConT (mkName "GHC.Prim.(->)") {- Prelude> :module +Language.Haskell.TH Prelude Language.Haskell.TH> AppT (AppT (ConT $ mkName "GHC.Prim.(->)") (ConT $ mkName "GHC.Base.Int")) (ConT $ mkName "Char") AppT (AppT (ConT GHC.Prim.(->)) (ConT GHC.Base.Int)) (ConT Char) Prelude Language.Haskell.TH> AppT (AppT ArrowT (ConT $ mkName "GHC.Base.Int")) (ConT $ mkName "Char") AppT (AppT ArrowT (ConT GHC.Base.Int)) (ConT Char) -} \end{code}