Old/sampou.org/GHCHacks_nobsun

GHCHacks_nobsun

GHCHacks:nobsun


GHCHacks by nobsun

準備

新しい構文要素の追加


GHCHacks by nobsun

純粋な関数型言語で非決定性を表現する手法として Pseudo data というものを 提案している10年以上前の論文があって、ずっと気になっている。Haskellの仕様 範囲ではこんな変なのは扱えないんだけど、これがあると More beautiful concurrency が実現できそう。でも処理系をつくらないと実証 できない。というわけで、GHC Hack

とは言うものの、GHG (GHC Hacking Guide) を青木さんが書いている…

わけないので:)、手探りでちょこちょこやることになる。どうなることやら。

準備

HEAD のソースを使う(なんと無謀な :)

% wget http://darcs.haskell.org/ghc-HEAD-2008-09-07-ghc-corelibs-testsuite.tar.gz

展開

% tar xvf ghc-HEAD-2008-09-07-ghc-corelibs-testsuite.tar.gz

darcs で最新状態にする

% cd ghc
% darcs pull -a -v
...
% ./darcs-all get
...
% ./darcs-all pull -a -v
...

とりあえず、この状態でビルドしてみることに。そのままだと時間がかかるので mk/build.mk をつくって、quickest ビルドする。

% cd mk
% cp build.mk.sample build.mk
% emacs build.mk
% cat build.mk
# -----------------------------------------------------------------------------
# A Sample build.mk
#
# Uncomment one of the following BuildFlavour settings to get the desired
# overall build type, and then tweak the options in the relevant section
# below.

# Uncomment one of these to select a build profile below:

# Full build with max optimisation (slow build)
#BuildFlavour = perf

# Fastest build (libs unoptimised):
BuildFlavour = quickest                        # ← ここをアンコメント

# Fast build with optimised libraries:
#BuildFlavour = quick

# A development build, working on the stage 1 compiler:
#BuildFlavour = devel1

# A development build, working on the stage 2 compiler:
#BuildFlavour = devel2

...

で、ビルド

% cd ..
% sh boot
...
% ./configure --prefix=$HOME
...
% make

ちゃんとビルドできれば、このソースツリーを出発点にする。 HEAD リポジトリは常に新しくなっている。 それゆえ、ビルドに失敗することもありうる。 その場合には、すこし時間を置いて darcs pull -a -v、./darcs-all pull -a -v を 再度試す。

  • shelarcy(2008/09/18 19:31:44 JST): GHC HEAD (Current) をビルドしたのなら、ghc/compiler/dist-stage2/doc/html/ghc の Haddock ドキュメントを見ると少し幸せになれるかも。(まだまだ、ソース内のコメントの Haddock 化は不十分ですが。)
  • あっ、build.mk に HADDOCK_DOCS = YES が入っていないので、ドキュメントは生成されていませんね。
  • nobsun(2008/09/18 22:10:55 JST): README には次のような記述がありますね。

    If you want the documentation too then use these commands instead:

        $ echo "XMLDocWays   = html" > mk/build.mk
        $ echo "HADDOCK_DOCS = YES" >> mk/build.mk
        $ sh boot
        $ ./configure
        $ make
        $ make install
        $ make install-docs

    These steps give you the default build, which includes everything optimised and built in various ways (eg. profiling libs are built). It can take a long time. To customise the build, see the file HACKING.

    今回はとにかく速くbuildすることに主眼を置いているので、こいつは無視しました。

  • とはいったものの、型の一覧だけであっても、一度つくっておけば便利そうなので やってみました。(2008/09/22 12:25:11 JST)

新しい構文要素の追加

「確定すると」a 型の値になるような値の型を型 a に対応する擬データ型という。 これは Pseudo a などと表現すればいいのだが {a} などという組込みの型構成子 を導入して簡潔な表現にしたい。

さてどうしよう(2008/09/18 16:39:15 JST)。

型推論できるところまで

diff -rN -u old-ghc/compiler/basicTypes/Unique.lhs new-ghc/compiler/basicTypes/Unique.lhs
--- old-ghc/compiler/basicTypes/Unique.lhs      2008-09-18 18:44:35.000000000 +0900
+++ new-ghc/compiler/basicTypes/Unique.lhs      2008-09-18 18:44:39.000000000 +0900
@@ -46,6 +46,7 @@
        mkPreludeMiscIdUnique, mkPreludeDataConUnique,
        mkPreludeTyConUnique, mkPreludeClassUnique,
        mkPArrDataConUnique,
+       mkPseudoDataConUnique,
 
        mkBuiltinUnique,
        mkPseudoUniqueC,
@@ -309,6 +310,7 @@
 mkPrimOpIdUnique       :: Int -> Unique
 mkPreludeMiscIdUnique  :: Int -> Unique
 mkPArrDataConUnique    :: Int -> Unique
+mkPseudoDataConUnique  :: Int -> Unique
 
 mkAlphaTyVarUnique i            = mkUnique '1' i
 
@@ -344,6 +346,8 @@
 -- tag 
 mkPArrDataConUnique a          = mkUnique ':' (2*a)
 
+mkPseudoDataConUnique a                = mkUnique '&' (2*a)
+
 -- The "tyvar uniques" print specially nicely: a, b, c, etc.
 -- See pprUnique for details
 
diff -rN -u old-ghc/compiler/hsSyn/HsTypes.lhs new-ghc/compiler/hsSyn/HsTypes.lhs
--- old-ghc/compiler/hsSyn/HsTypes.lhs  2008-09-18 18:44:35.000000000 +0900
+++ new-ghc/compiler/hsSyn/HsTypes.lhs  2008-09-18 18:44:40.000000000 +0900
@@ -130,6 +130,8 @@
 
   | HsPArrTy           (LHsType name)  -- Elem. type of parallel array: [:t:]
 
+  | HsPseudoTy         (LHsType name)  -- Elem. type of pseudo data: {t}
+
   | HsTupleTy          Boxity
                        [LHsType name]  -- Element types (length gives arity)
 
diff -rN -u old-ghc/compiler/parser/Parser.y.pp new-ghc/compiler/parser/Parser.y.pp
--- old-ghc/compiler/parser/Parser.y.pp 2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/parser/Parser.y.pp 2008-09-18 18:44:40.000000000 +0900
@@ -1055,6 +1055,7 @@
        | '(#' comma_types1 '#)'        { LL $ HsTupleTy Unboxed $2     }
        | '[' ctype ']'                 { LL $ HsListTy  $2 }
        | '[:' ctype ':]'               { LL $ HsPArrTy  $2 }
+       | '{' ctype '}'                 { LL $ HsPseudoTy   $2 }
        | '(' ctype ')'                 { LL $ HsParTy   $2 }
        | '(' ctype '::' kind ')'       { LL $ HsKindSig $2 (unLoc $4) }
 -- Generics
diff -rN -u old-ghc/compiler/parser/RdrHsSyn.lhs new-ghc/compiler/parser/RdrHsSyn.lhs
--- old-ghc/compiler/parser/RdrHsSyn.lhs        2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/parser/RdrHsSyn.lhs        2008-09-18 18:44:40.000000000 +0900
@@ -118,6 +118,7 @@
       HsAppTy ty1 ty2                  -> extract_lty ty1 (extract_lty ty2 acc)
       HsListTy ty                      -> extract_lty ty acc
       HsPArrTy ty                      -> extract_lty ty acc
+      HsPseudoTy ty                    -> extract_lty ty acc
       HsTupleTy _ tys                  -> foldr extract_lty acc tys
       HsFunTy ty1 ty2                  -> extract_lty ty1 (extract_lty ty2 acc)
       HsPredTy p               -> extract_pred p acc
diff -rN -u old-ghc/compiler/prelude/PrelNames.lhs new-ghc/compiler/prelude/PrelNames.lhs
--- old-ghc/compiler/prelude/PrelNames.lhs      2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/prelude/PrelNames.lhs      2008-09-18 18:44:40.000000000 +0900
@@ -232,7 +232,7 @@
 pRELUDE                = mkBaseModule_ pRELUDE_NAME
 
 gHC_PRIM, gHC_TYPES, gHC_BOOL, gHC_UNIT, gHC_ORDERING, gHC_GENERICS, gHC_CLASSES, gHC_BASE, gHC_ENUM,
-    gHC_SHOW, gHC_READ, gHC_NUM, gHC_INTEGER, gHC_LIST, gHC_PARR,
+    gHC_SHOW, gHC_READ, gHC_NUM, gHC_INTEGER, gHC_LIST, gHC_PARR, gHC_PSEUDO,
     gHC_TUPLE, dATA_TUPLE, dATA_EITHER, dATA_STRING, gHC_PACK, gHC_CONC, gHC_IO_BASE,
     gHC_ST, gHC_ARR, gHC_STABLE, gHC_ADDR, gHC_PTR, gHC_ERR, gHC_REAL,
     gHC_FLOAT, gHC_TOP_HANDLER, sYSTEM_IO, dYNAMIC, tYPEABLE, gENERICS,
@@ -253,6 +253,7 @@
 gHC_INTEGER    = mkIntegerModule (fsLit "GHC.Integer")
 gHC_LIST       = mkBaseModule (fsLit "GHC.List")
 gHC_PARR       = mkBaseModule (fsLit "GHC.PArr")
+gHC_PSEUDO     = mkBaseModule (fsLit "GHC.Pseudo")
 gHC_TUPLE      = mkPrimModule (fsLit "GHC.Tuple")
 dATA_TUPLE     = mkBaseModule (fsLit "Data.Tuple")
 dATA_EITHER    = mkBaseModule (fsLit "Data.Either")
@@ -1022,6 +1023,10 @@
 stringTyConKey :: Unique
 stringTyConKey                         = mkPreludeTyConUnique 134
 
+-- Pseudo data type constructor
+pseudoTyConKey :: Unique
+pseudoTyConKey                         = mkPreludeTyConUnique 135
+
 ---------------- Template Haskell -------------------
 --     USES TyConUniques 100-129
 -----------------------------------------------------
@@ -1068,6 +1073,10 @@
 leftDataConKey, rightDataConKey :: Unique
 leftDataConKey                         = mkPreludeDataConUnique 25
 rightDataConKey                                = mkPreludeDataConUnique 26
+
+-- Data constructor for pseudo data (only in pattern)
+pseudoDataConKey :: Unique
+pseudoDataConKey                       = mkPreludeDataConUnique 27
 \end{code}
 
 %************************************************************************
diff -rN -u old-ghc/compiler/prelude/TysWiredIn.lhs new-ghc/compiler/prelude/TysWiredIn.lhs
--- old-ghc/compiler/prelude/TysWiredIn.lhs     2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/prelude/TysWiredIn.lhs     2008-09-18 18:44:40.000000000 +0900
@@ -53,7 +53,12 @@
         -- * Parallel arrays
        mkPArrTy,
        parrTyCon, parrFakeCon, isPArrTyCon, isPArrFakeCon,
-       parrTyCon_RDR, parrTyConName
+       parrTyCon_RDR, parrTyConName,
+
+        -- * Pseudo data
+       mkPseudoTy,
+       pseudoTyCon, isPseudoTyCon,
+       pseudoTyCon_RDR, pseudoTyConName
     ) where
 
 import {-# SOURCE #-} MkId( mkDataConIds )
@@ -86,7 +91,7 @@
                           rightCoercionTyCon, instCoercionTyCon )
 import TypeRep          ( mkArrowKinds, liftedTypeKind, ubxTupleKind )
 import Unique          ( incrUnique, mkTupleTyConUnique,
-                         mkTupleDataConUnique, mkPArrDataConUnique )
+                         mkTupleDataConUnique, mkPArrDataConUnique, mkPseudoDataConUnique )
 import Array
 import FastString
 import Outputable
@@ -129,6 +134,7 @@
              , intTyCon
              , listTyCon
              , parrTyCon
+             , pseudoTyCon
               , unsafeCoercionTyCon
               , symCoercionTyCon
               , transCoercionTyCon
@@ -177,8 +183,12 @@
 parrTyConName    = mkWiredInTyConName   BuiltInSyntax gHC_PARR (fsLit "[::]") parrTyConKey parrTyCon 
 parrDataConName   = mkWiredInDataConName UserSyntax    gHC_PARR (fsLit "PArr") parrDataConKey parrDataCon
 
+pseudoTyConName, pseudoDataConName :: Name
+pseudoTyConName          = mkWiredInTyConName   BuiltInSyntax gHC_PSEUDO (fsLit "{}") pseudoTyConKey pseudoTyCon 
+pseudoDataConName = mkWiredInDataConName UserSyntax    gHC_PSEUDO (fsLit "{}") pseudoDataConKey pseudoDataCon
+
 boolTyCon_RDR, false_RDR, true_RDR, intTyCon_RDR, charTyCon_RDR,
-    intDataCon_RDR, listTyCon_RDR, consDataCon_RDR, parrTyCon_RDR:: RdrName
+    intDataCon_RDR, listTyCon_RDR, consDataCon_RDR, parrTyCon_RDR, pseudoTyCon_RDR:: RdrName
 boolTyCon_RDR   = nameRdrName boolTyConName
 false_RDR      = nameRdrName falseDataConName
 true_RDR       = nameRdrName trueDataConName
@@ -188,6 +198,7 @@
 listTyCon_RDR  = nameRdrName listTyConName
 consDataCon_RDR = nameRdrName consDataConName
 parrTyCon_RDR  = nameRdrName parrTyConName
+pseudoTyCon_RDR        = nameRdrName pseudoTyConName
 {-
 tySuperKindTyCon_RDR     = nameRdrName tySuperKindTyConName
 coSuperKindTyCon_RDR = nameRdrName coSuperKindTyConName
@@ -616,4 +627,38 @@
 isPArrFakeCon dcon  = dcon == parrFakeCon (dataConSourceArity dcon)
 \end{code}
 
+%************************************************************************
+%*                                                                     *
+\subsection[TysWiredIn-Pseudo]{The @{}@ type}
+%*                                                                     *
+%************************************************************************
+
+Special syntax for pseudo data needs some wired in definitions.
+
+\begin{code}
+-- | Construct a type representing the application of the parallel array constructor 
+mkPseudoTy    :: Type -> Type
+mkPseudoTy ty  = mkTyConApp pseudoTyCon [ty]
 
+-- | Represents the type constructor of pseudo data
+--
+--  * This must match the definition in @[email protected]
+--
+-- NB: Although the constructor is given here, it will not be accessible in
+--     user code as it is not in the environment of any compiled module except
+--     @[email protected]
+--
+pseudoTyCon :: TyCon
+pseudoTyCon  = pcNonRecDataTyCon pseudoTyConName alpha_tyvar [pseudoDataCon]
+
+pseudoDataCon :: DataCon
+pseudoDataCon  = pcDataCon 
+                pseudoDataConName 
+                alpha_tyvar            -- forall'ed type variables
+                alpha_ty
+                pseudoTyCon
+
+-- | Check whether a type constructor is the constructor for pseudo data
+isPseudoTyCon    :: TyCon -> Bool
+isPseudoTyCon tc  = tyConName tc == pseudoTyConName
+\end{code}
diff -rN -u old-ghc/compiler/rename/RnHsSyn.lhs new-ghc/compiler/rename/RnHsSyn.lhs
--- old-ghc/compiler/rename/RnHsSyn.lhs 2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/rename/RnHsSyn.lhs 2008-09-18 18:44:40.000000000 +0900
@@ -6,7 +6,7 @@
 \begin{code}
 module RnHsSyn(
         -- Names
-        charTyCon_name, listTyCon_name, parrTyCon_name, tupleTyCon_name,
+        charTyCon_name, listTyCon_name, parrTyCon_name, pseudoTyCon_name, tupleTyCon_name,
         extractHsTyVars, extractHsTyNames, extractHsTyNames_s,
         extractFunDepNames, extractHsCtxtTyNames, extractHsPredTyNames,
 
@@ -20,7 +20,7 @@
 
 import HsSyn
 import Class            ( FunDep )
-import TysWiredIn       ( tupleTyCon, listTyCon, parrTyCon, charTyCon )
+import TysWiredIn       ( tupleTyCon, listTyCon, parrTyCon, pseudoTyCon, charTyCon )
 import Name             ( Name, getName, isTyVarName )
 import NameSet
 import BasicTypes       ( Boxity )
@@ -36,10 +36,11 @@
 These free-variable finders returns tycons and classes too.
 
 \begin{code}
-charTyCon_name, listTyCon_name, parrTyCon_name :: Name
+charTyCon_name, listTyCon_name, parrTyCon_name, pseudoTyCon_name :: Name
 charTyCon_name    = getName charTyCon
 listTyCon_name    = getName listTyCon
 parrTyCon_name    = getName parrTyCon
+pseudoTyCon_name  = getName pseudoTyCon
 
 tupleTyCon_name :: Boxity -> Int -> Name
 tupleTyCon_name boxity n = getName (tupleTyCon boxity n)
@@ -59,6 +60,7 @@
     get (HsAppTy ty1 ty2)      = getl ty1 `unionNameSets` getl ty2
     get (HsListTy ty)          = unitNameSet listTyCon_name `unionNameSets` getl ty
     get (HsPArrTy ty)          = unitNameSet parrTyCon_name `unionNameSets` getl ty
+    get (HsPseudoTy ty)        = unitNameSet pseudoTyCon_name `unionNameSets` getl ty
     get (HsTupleTy _ tys)      = extractHsTyNames_s tys
     get (HsFunTy ty1 ty2)      = getl ty1 `unionNameSets` getl ty2
     get (HsPredTy p)           = extractHsPredTyNames p
diff -rN -u old-ghc/compiler/rename/RnTypes.lhs new-ghc/compiler/rename/RnTypes.lhs
--- old-ghc/compiler/rename/RnTypes.lhs 2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/rename/RnTypes.lhs 2008-09-18 18:44:40.000000000 +0900
@@ -155,6 +155,10 @@
     ty' <- rnLHsType doc ty
     return (HsPArrTy ty')
 
+rnHsType doc (HsPseudoTy ty) = do
+    ty' <- rnLHsType doc ty
+    return (HsPseudoTy ty')
+
 -- Unboxed tuples are allowed to have poly-typed arguments.  These
 -- sometimes crop up as a result of CPR worker-wrappering dictionaries.
 rnHsType doc (HsTupleTy tup_con tys) = do
diff -rN -u old-ghc/compiler/typecheck/TcHsType.lhs new-ghc/compiler/typecheck/TcHsType.lhs
--- old-ghc/compiler/typecheck/TcHsType.lhs     2008-09-18 18:44:36.000000000 +0900
+++ new-ghc/compiler/typecheck/TcHsType.lhs     2008-09-18 18:44:40.000000000 +0900
@@ -306,6 +306,10 @@
     ty' <- kcLiftedType ty
     return (HsPArrTy ty', liftedTypeKind)
 
+kc_hs_type (HsPseudoTy ty) = do
+    ty' <- kcLiftedType ty
+    return (HsPseudoTy ty', liftedTypeKind)
+
 kc_hs_type (HsNumTy n)
    = return (HsNumTy n, liftedTypeKind)
 
@@ -500,6 +504,11 @@
     checkWiredInTyCon parrTyCon
     return (mkPArrTy tau_ty)
 
+ds_type (HsPseudoTy ty) = do
+    tau_ty <- dsHsType ty
+    checkWiredInTyCon pseudoTyCon
+    return (mkPseudoTy tau_ty)
+
 ds_type (HsTupleTy boxity tys) = do
     tau_tys <- dsHsTypes tys
     checkWiredInTyCon tycon

おっと、GHC.Pseudo.hs を追加したんだ

% cd libraries/base
% darcs diff -u
diff -rN -u old-base/GHC/Pseudo.hs new-base/GHC/Pseudo.hs
--- old-base/GHC/Pseudo.hs      1970-01-01 09:00:00.000000000 +0900
+++ new-base/GHC/Pseudo.hs      2008-09-18 19:31:47.000000000 +0900
@@ -0,0 +1,9 @@
+{-# OPTIONS_GHC -XNoImplicitPrelude #-}
+{-# OPTIONS_HADDOCK hide #-}
+module GHC.Pseudo (deref) where
+
+import GHC.Err
+
+deref :: {a} -> a
+deref = error "GHC.Pseudo.deref: not yet implemented"
+
diff -rN -u old-base/base.cabal new-base/base.cabal
--- old-base/base.cabal 2008-09-18 19:31:47.000000000 +0900
+++ new-base/base.cabal 2008-09-18 19:31:47.000000000 +0900
@@ -43,6 +43,7 @@
             GHC.List,
             GHC.Num,
             GHC.PArr,
+            GHC.Pseudo,
             GHC.Pack,
             GHC.Ptr,
             GHC.Read,

% cd ../..

ビルドして、インストールして試してみる

% make && make install
...
% export PATH=$HOME/bin:$PATH
% ghci
GHCi, version 6.9.20080917: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> let { f :: {a} ; f = undefined }
Prelude> :type f
f :: {} a
Prelude> let { g :: {a} -> b ; g = undefined }
Prelude> :type g
g :: {} a -> b
Prelude> :type g f
g f :: b
Prelude> 

ううむ。プリティプリント辺りに手を入れないと。。。

今日(2008/09/18 19:39:15 JST)はここまで とりあえず、ローカルにコミット

% darcs record -a
...
% cd libraries/base
% darcs record -a

型のプリティプリント

型のpprあたりは、帰宅途中の電車 de Hack! でできたみたい。

diff -rN -u old-ghc/compiler/hsSyn/HsTypes.lhs new-ghc/compiler/hsSyn/HsTypes.lhs
--- old-ghc/compiler/hsSyn/HsTypes.lhs  2008-09-18 21:45:36.000000000 +0900
+++ new-ghc/compiler/hsSyn/HsTypes.lhs  2008-09-18 21:45:42.000000000 +0900
@@ -360,6 +360,7 @@
 ppr_mono_ty _         (HsKindSig ty kind) = parens (ppr_mono_lty pREC_TOP ty <+> dcolon <+> pprKind kind)
 ppr_mono_ty _         (HsListTy ty)      = brackets (ppr_mono_lty pREC_TOP ty)
 ppr_mono_ty _         (HsPArrTy ty)      = pabrackets (ppr_mono_lty pREC_TOP ty)
+ppr_mono_ty _         (HsPseudoTy ty)    = braces (ppr_mono_lty pREC_TOP ty)
 ppr_mono_ty _         (HsPredTy pred)     = ppr pred
 ppr_mono_ty _         (HsNumTy n)         = integer n  -- generics only
 ppr_mono_ty _         (HsSpliceTy s)      = pprSplice s
diff -rN -u old-ghc/compiler/iface/BinIface.hs new-ghc/compiler/iface/BinIface.hs
--- old-ghc/compiler/iface/BinIface.hs  2008-09-18 21:45:36.000000000 +0900
+++ new-ghc/compiler/iface/BinIface.hs  2008-09-18 21:45:42.000000000 +0900
@@ -899,13 +899,14 @@
    put_ bh IfaceCharTc               = putByte bh 3
    put_ bh IfaceListTc               = putByte bh 4
    put_ bh IfacePArrTc               = putByte bh 5
-   put_ bh IfaceLiftedTypeKindTc   = putByte bh 6
-   put_ bh IfaceOpenTypeKindTc     = putByte bh 7
-   put_ bh IfaceUnliftedTypeKindTc = putByte bh 8
-   put_ bh IfaceUbxTupleKindTc     = putByte bh 9
-   put_ bh IfaceArgTypeKindTc      = putByte bh 10
-   put_ bh (IfaceTupTc bx ar) = do { putByte bh 11; put_ bh bx; put_ bh ar }
-   put_ bh (IfaceTc ext)      = do { putByte bh 12; put_ bh ext }
+   put_ bh IfacePseudoTc      = putByte bh 6
+   put_ bh IfaceLiftedTypeKindTc   = putByte bh 7
+   put_ bh IfaceOpenTypeKindTc     = putByte bh 8
+   put_ bh IfaceUnliftedTypeKindTc = putByte bh 9
+   put_ bh IfaceUbxTupleKindTc     = putByte bh 10
+   put_ bh IfaceArgTypeKindTc      = putByte bh 11
+   put_ bh (IfaceTupTc bx ar) = do { putByte bh 12; put_ bh bx; put_ bh ar }
+   put_ bh (IfaceTc ext)      = do { putByte bh 13; put_ bh ext }
 
    get bh = do
        h <- getByte bh
@@ -915,12 +916,13 @@
          3 -> return IfaceCharTc
          4 -> return IfaceListTc
          5 -> return IfacePArrTc
-          6 -> return IfaceLiftedTypeKindTc 
-          7 -> return IfaceOpenTypeKindTc 
-          8 -> return IfaceUnliftedTypeKindTc
-          9 -> return IfaceUbxTupleKindTc
-          10 -> return IfaceArgTypeKindTc
-         11 -> do { bx <- get bh; ar <- get bh; return (IfaceTupTc bx ar) }
+         6 -> return IfacePseudoTc
+          7 -> return IfaceLiftedTypeKindTc 
+          8 -> return IfaceOpenTypeKindTc 
+          9 -> return IfaceUnliftedTypeKindTc
+          10 -> return IfaceUbxTupleKindTc
+          11 -> return IfaceArgTypeKindTc
+         12 -> do { bx <- get bh; ar <- get bh; return (IfaceTupTc bx ar) }
          _ -> do { ext <- get bh; return (IfaceTc ext) }
 
 instance Binary IfacePredType where
diff -rN -u old-ghc/compiler/iface/IfaceType.lhs new-ghc/compiler/iface/IfaceType.lhs
--- old-ghc/compiler/iface/IfaceType.lhs        2008-09-18 21:45:36.000000000 +0900
+++ new-ghc/compiler/iface/IfaceType.lhs        2008-09-18 21:45:42.000000000 +0900
@@ -73,7 +73,7 @@
 data IfaceTyCon        -- Abbreviations for common tycons with known names
   = IfaceTc Name       -- The common case
   | IfaceIntTc | IfaceBoolTc | IfaceCharTc
-  | IfaceListTc | IfacePArrTc
+  | IfaceListTc | IfacePArrTc | IfacePseudoTc
   | IfaceTupTc Boxity Arity 
   | IfaceLiftedTypeKindTc | IfaceOpenTypeKindTc | IfaceUnliftedTypeKindTc
   | IfaceUbxTupleKindTc | IfaceArgTypeKindTc 
@@ -85,6 +85,7 @@
 ifaceTyConName IfaceCharTc       = charTyConName
 ifaceTyConName IfaceListTc       = listTyConName
 ifaceTyConName IfacePArrTc       = parrTyConName
+ifaceTyConName IfacePseudoTc     = pseudoTyConName
 ifaceTyConName (IfaceTupTc bx ar) = getName (tupleTyCon bx ar)
 ifaceTyConName IfaceLiftedTypeKindTc   = liftedTypeKindTyConName
 ifaceTyConName IfaceOpenTypeKindTc     = openTypeKindTyConName
@@ -223,6 +224,7 @@
 ppr_tc_app _         tc         []   = ppr_tc tc
 ppr_tc_app _         IfaceListTc [ty] = brackets   (pprIfaceType ty)
 ppr_tc_app _         IfacePArrTc [ty] = pabrackets (pprIfaceType ty)
+ppr_tc_app _         IfacePseudoTc [ty] = braces (pprIfaceType ty)
 ppr_tc_app _         (IfaceTupTc bx arity) tys
   | arity == length tys 
   = tupleParens bx (sep (punctuate comma (map pprIfaceType tys)))
@@ -329,6 +331,7 @@
   | nm == charTyConName             = IfaceCharTc 
   | nm == listTyConName             = IfaceListTc 
   | nm == parrTyConName             = IfacePArrTc 
+  | nm == pseudoTyConName           = IfacePseudoTc 
   | nm == liftedTypeKindTyConName   = IfaceLiftedTypeKindTc
   | nm == unliftedTypeKindTyConName = IfaceUnliftedTypeKindTc
   | nm == openTypeKindTyConName     = IfaceOpenTypeKindTc
diff -rN -u old-ghc/compiler/types/TypeRep.lhs new-ghc/compiler/types/TypeRep.lhs
--- old-ghc/compiler/types/TypeRep.lhs  2008-09-18 21:45:38.000000000 +0900
+++ new-ghc/compiler/types/TypeRep.lhs  2008-09-18 21:45:42.000000000 +0900
@@ -507,6 +507,7 @@
 ppr_tc_app _ tc [ty]
   | tc `hasKey` listTyConKey = brackets (pprType ty)
   | tc `hasKey` parrTyConKey = ptext (sLit "[:") <> pprType ty <> ptext (sLit ":]")
+  | tc `hasKey` pseudoTyConKey = braces (pprType ty)
   | tc `hasKey` liftedTypeKindTyConKey   = ptext (sLit "*")
   | tc `hasKey` unliftedTypeKindTyConKey = ptext (sLit "#")
   | tc `hasKey` openTypeKindTyConKey     = ptext (sLit "(?)")

で build して install

% make distclean
...
% sh boot
...
% ./configure --prefix=$HOME
...
% make && make install
...

さきほどの実行例をもう一度

Prelude> let { f :: {a} ; f = undefined }
Prelude> :type f
f :: {a}
Prelude> let { g :: {Int} -> Integer ; g = undefined }
Prelude> :type g
g :: {Int} -> Integer
Prelude> :type g f
g f :: Integer
Prelude> 

OK!!!

落穂ひろい

ちょい抜けてた

diff -rN -u old-ghc/compiler/iface/TcIface.lhs new-ghc/compiler/iface/TcIface.lhs
--- old-ghc/compiler/iface/TcIface.lhs  2008-09-19 17:02:29.000000000 +0900
+++ new-ghc/compiler/iface/TcIface.lhs  2008-09-19 17:02:36.000000000 +0900
@@ -1056,6 +1056,7 @@
 tcIfaceTyCon IfaceCharTc       = tcWiredInTyCon charTyCon
 tcIfaceTyCon IfaceListTc       = tcWiredInTyCon listTyCon
 tcIfaceTyCon IfacePArrTc       = tcWiredInTyCon parrTyCon
+tcIfaceTyCon IfacePseudoTc     = tcWiredInTyCon pseudoTyCon
 tcIfaceTyCon (IfaceTupTc bx ar) = tcWiredInTyCon (tupleTyCon bx ar)
 tcIfaceTyCon (IfaceTc name)     = do { thing <- tcIfaceGlobal name 
                                     ; return (check_tc (tyThingTyCon thing)) }
diff -rN -u old-ghc/compiler/parser/Lexer.x new-ghc/compiler/parser/Lexer.x

組込みの後置演算子 ?

擬データの確定を強制する単項後置演算子 ・? を導入する。

diff -rN -u old-ghc/compiler/hsSyn/HsExpr.lhs new-ghc/compiler/hsSyn/HsExpr.lhs
--- old-ghc/compiler/hsSyn/HsExpr.lhs   2008-09-19 17:02:29.000000000 +0900
+++ new-ghc/compiler/hsSyn/HsExpr.lhs   2008-09-19 17:02:36.000000000 +0900
@@ -108,6 +108,9 @@
   | NegApp      (LHsExpr id)    -- negated expr
                 (SyntaxExpr id) -- Name of 'negate'
 
+  | PdDerefApp  (LHsExpr id)    -- dereferenced pseudo data var
+                (SyntaxExpr id) -- Name of 'dereference'
+
   | HsPar       (LHsExpr id)    -- parenthesised expr
 
   | SectionL    (LHsExpr id)    -- operand
@@ -349,6 +352,8 @@
 
 ppr_expr (NegApp e _) = char '-' <+> pprDebugParendExpr e
 
+ppr_expr (PdDerefApp e _) = pprDebugParendExpr e <> char '?'
+
 ppr_expr (SectionL expr op)
   = case unLoc op of
       HsVar v -> pp_infixly v
diff -rN -u old-ghc/compiler/parser/Lexer.x new-ghc/compiler/parser/Lexer.x
--- old-ghc/compiler/parser/Lexer.x     2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/parser/Lexer.x     2008-09-19 17:02:36.000000000 +0900
@@ -326,6 +326,10 @@
 }
 
 <0> {
+  @varid \?     { chop_one_varid ITPDderefvarid }
+}
+
+<0> {
   "(#" / { ifExtension unboxedTuplesEnabled `alexAndPred` notFollowedBySymbol }
          { token IToubxparen }
   "#)" / { ifExtension unboxedTuplesEnabled }
@@ -529,6 +533,8 @@
 
   | ITdupipvarid   FastString  -- GHC extension: implicit param: ?x
 
+  | ITPDderefvarid   FastString   -- Psudo data dereference: x?
+
   | ITpragma StringBuffer
 
   | ITchar       Char
@@ -724,6 +730,10 @@
 skip_one_varid f span buf len 
   = return (L span $! f (lexemeToFastString (stepOn buf) (len-1)))
 
+chop_one_varid :: (FastString -> Token) -> Action
+chop_one_varid f span buf len
+ = return (L span $! f (lexemeToFastString buf (len-1)))
+
 strtoken :: (String -> Token) -> Action
 strtoken f span buf len = 
   return (L span $! (f $! lexemeToString buf len))
diff -rN -u old-ghc/compiler/parser/Parser.y.pp new-ghc/compiler/parser/Parser.y.pp
--- old-ghc/compiler/parser/Parser.y.pp 2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/parser/Parser.y.pp 2008-09-19 17:02:36.000000000 +0900
@@ -316,6 +316,7 @@
  QCONSYM       { L _ (ITqconsym  _) }
 
  IPDUPVARID    { L _ (ITdupipvarid   _) }              -- GHC extension
+ PDDEREFVARID          { L _ (ITPDderefvarid   _) }            -- dereference pseudo data
 
  CHAR          { L _ (ITchar     _) }
  STRING                { L _ (ITstring   _) }
@@ -1376,6 +1377,7 @@
 
 aexp2  :: { LHsExpr RdrName }
        : ipvar                         { L1 (HsIPVar $! unLoc $1) }
+        | pdderefvar                    { $1 }
        | qcname                        { L1 (HsVar   $! unLoc $1) }
        | literal                       { L1 (HsLit   $! unLoc $1) }
 -- This will enable overloaded strings permanently.  Normally the renamer turns HsString
@@ -1549,6 +1551,12 @@
 -- We are reusing `lexps' and `flattenedpquals' from the list case.
 
 -----------------------------------------------------------------------------
+-- Dereferenced pseudo data var
+
+pdderefvar :: { LHsExpr RdrName }
+        : PDDEREFVARID { LL (mkHsPdDerefApp (L1 (HsVar (mkUnqual varName (getPDDEREFVARID $1))))) }
+
+-----------------------------------------------------------------------------
 -- Guards
 
 guardquals :: { Located [LStmt RdrName] }
@@ -1989,6 +1997,7 @@
 getQVARSYM     (L _ (ITqvarsym  x)) = x
 getQCONSYM     (L _ (ITqconsym  x)) = x
 getIPDUPVARID   (L _ (ITdupipvarid   x)) = x
+getPDDEREFVARID (L _ (ITPDderefvarid x)) = x
 getCHAR                (L _ (ITchar     x)) = x
 getSTRING      (L _ (ITstring   x)) = x
 getINTEGER     (L _ (ITinteger  x)) = x
diff -rN -u old-ghc/compiler/parser/RdrHsSyn.lhs new-ghc/compiler/parser/RdrHsSyn.lhs
--- old-ghc/compiler/parser/RdrHsSyn.lhs        2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/parser/RdrHsSyn.lhs        2008-09-19 17:02:36.000000000 +0900
@@ -17,6 +17,7 @@
  
        mkHsOpApp, mkClassDecl,
        mkHsIntegral, mkHsFractional, mkHsIsString,
+        mkHsPdDerefApp,
        mkHsDo, mkHsSplice,
         mkTyData, mkPrefixCon, mkRecCon, mkInlineSpec, 
        mkRecConstrOrUpdate, -- HsExp -> [HsFieldUpdate] -> P HsExp
@@ -200,6 +201,11 @@
             tcdKindSig = ksig, tcdDerivs = maybe_deriv }
 \end{code}
 
+\begin{code}
+mkHsPdDerefApp :: LHsExpr RdrName -> HsExpr RdrName
+mkHsPdDerefApp v = PdDerefApp v noSyntaxExpr
+\end{code}
+
 %************************************************************************
 %*                                                                     *
 \subsection[cvBinds-etc]{Converting to @[email protected], etc.}
diff -rN -u old-ghc/compiler/prelude/PrelNames.lhs new-ghc/compiler/prelude/PrelNames.lhs
--- old-ghc/compiler/prelude/PrelNames.lhs      2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/prelude/PrelNames.lhs      2008-09-19 17:02:36.000000000 +0900
@@ -212,6 +212,9 @@
        -- dotnet interop
        , objectTyConName, marshalObjectName, unmarshalObjectName
        , marshalStringName, unmarshalStringName, checkDotnetResName
+
+        -- pseudo data
+        , pdDerefName
     ]
 
 genericTyConNames :: [Name]
@@ -796,12 +799,14 @@
        -- objectTyConName was "wTcQual", but that's gone now, and
        -- I can't see why it was wired in anyway...
 unmarshalObjectName, marshalObjectName, marshalStringName,
-    unmarshalStringName, checkDotnetResName :: Name
+    unmarshalStringName, checkDotnetResName, pdDerefName :: Name
 unmarshalObjectName = varQual  dOTNET (fsLit "unmarshalObject") unmarshalObjectIdKey
 marshalObjectName   = varQual  dOTNET (fsLit "marshalObject") marshalObjectIdKey
 marshalStringName   = varQual  dOTNET (fsLit "marshalString") marshalStringIdKey
 unmarshalStringName = varQual  dOTNET (fsLit "unmarshalString") unmarshalStringIdKey
 checkDotnetResName  = varQual  dOTNET (fsLit "checkResult")     checkDotnetResNameIdKey
+
+pdDerefName         = varQual gHC_PSEUDO (fsLit "deref") pdDerefIdKey
 \end{code}
 
 %************************************************************************
@@ -1258,6 +1263,11 @@
 fromStringClassOpKey :: Unique
 fromStringClassOpKey         = mkPreludeMiscIdUnique 125
 
+-- pseudo data dereference
+pdDerefIdKey :: Unique
+pdDerefIdKey                  = mkPreludeMiscIdUnique 126
+
+
 ---------------- Template Haskell -------------------
 --     USES IdUniques 200-399
 -----------------------------------------------------
diff -rN -u old-ghc/compiler/rename/RnExpr.lhs new-ghc/compiler/rename/RnExpr.lhs
--- old-ghc/compiler/rename/RnExpr.lhs  2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/rename/RnExpr.lhs  2008-09-19 17:02:37.000000000 +0900
@@ -27,13 +27,13 @@
 import TcRnMonad
 import RnEnv
 import RnTypes         ( rnHsTypeFVs, 
-                         mkOpFormRn, mkOpAppRn, mkNegAppRn, checkSectionPrec)
+                         mkOpFormRn, mkOpAppRn, mkNegAppRn, mkPdDerefAppRn, checkSectionPrec)
 import RnPat
 import DynFlags                ( DynFlag(..) )
 import BasicTypes      ( FixityDirection(..) )
 import PrelNames       ( thFAKE, hasKey, assertIdKey, assertErrorName,
                          loopAName, choiceAName, appAName, arrAName, composeAName, firstAName,
-                         negateName, thenMName, bindMName, failMName, groupWithName )
+                         negateName, pdDerefName, thenMName, bindMName, failMName, groupWithName )
 
 import Name
 import NameSet
@@ -166,6 +166,12 @@
     mkNegAppRn e' neg_name     `thenM` \ final_e ->
     returnM (final_e, fv_e `plusFV` fv_neg)
 
+rnExpr (PdDerefApp e _)
+  = rnLExpr e                   `thenM` \ (e', fv_e) ->
+    lookupSyntaxName pdDerefName `thenM` \ (deref_name, fv_deref) ->
+    mkPdDerefAppRn e' deref_name `thenM` \ final_e ->
+    returnM (final_e, fv_e `plusFV` fv_deref)
+
 ------------------------------------------
 -- Template Haskell extensions
 -- Don't ifdef-GHCI them because we want to fail gracefully
diff -rN -u old-ghc/compiler/rename/RnTypes.lhs new-ghc/compiler/rename/RnTypes.lhs
--- old-ghc/compiler/rename/RnTypes.lhs 2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/rename/RnTypes.lhs 2008-09-19 17:02:37.000000000 +0900
@@ -10,7 +10,7 @@
        rnHsSigType, rnHsTypeFVs,
 
        -- Precence related stuff
-       mkOpAppRn, mkNegAppRn, mkOpFormRn, mkConOpPatRn,
+       mkOpAppRn, mkNegAppRn, mkPdDerefAppRn, mkOpFormRn, mkConOpPatRn,
        checkPrecMatch, checkSectionPrec
   ) where
 
@@ -378,6 +378,11 @@
   = ASSERT( not_op_app (unLoc neg_arg) )
     return (NegApp neg_arg neg_name)
 
+mkPdDerefAppRn :: LHsExpr id -> SyntaxExpr id -> RnM (HsExpr id)
+mkPdDerefAppRn deref_arg deref_name
+  = ASSERT( not_op_app (unLoc deref_arg) )
+    return (PdDerefApp deref_arg deref_name)
+
 not_op_app :: HsExpr id -> Bool
 not_op_app (OpApp _ _ _ _) = False
 not_op_app _              = True
diff -rN -u old-ghc/compiler/typecheck/TcExpr.lhs new-ghc/compiler/typecheck/TcExpr.lhs
--- old-ghc/compiler/typecheck/TcExpr.lhs       2008-09-19 17:02:30.000000000 +0900
+++ new-ghc/compiler/typecheck/TcExpr.lhs       2008-09-19 17:02:37.000000000 +0900
@@ -170,6 +170,9 @@
        ; expr' <- tcMonoExpr expr res_ty
        ; return (NegApp expr' neg_expr') }
 
+tcExpr (PdDerefApp expr deref_expr) res_ty
+  = tcExpr (HsApp df expr) res_ty where df = L (getLoc expr) (HsVar pdDerefName)
+
 tcExpr (HsIPVar ip) res_ty
   = do { let origin = IPOccOrigin ip
                -- Implicit parameters must have a *tau-type* not a 

実行してみる

*Main> let { y :: { Integer }; y = undefined }
*Main> let z = y?
*Main> :t z
z :: Integer
*Main> :t ?

<interactive>:1:0: parse error on input `?'
*Main> :t (?)

<interactive>:1:0: Not in scope: `?'

? 単独では型を問いあわせられないけど、意図した型にはなっている。


Last modified : 2008/09/22 12:25:11 JST