#7064: TH: Pragmas refactoring (also adds RULES and 'SPECIALIZE instance' 
support)
[patch]
--------------------------------+-------------------------------------------
 Reporter:  mikhail.vorozhtsov  |          Owner:                  
     Type:  bug                 |         Status:  new             
 Priority:  normal              |      Component:  Template Haskell
  Version:  7.5                 |       Keywords:                  
       Os:  Unknown/Multiple    |   Architecture:  Unknown/Multiple
  Failure:  None/Unknown        |       Testcase:                  
Blockedby:                      |       Blocking:                  
  Related:                      |  
--------------------------------+-------------------------------------------
 I noticed that currently there is not way to define "SPECIALIZE + phase"
 pragma from TH, only "SPECIALIZE (NO)INLINE + phase". One thing led to
 another, and I ended up refactoring the Pragma data type. Attached patches

   * Allow "SPECIALIZE + phase" pragma
   * Replace `Maybe (Bool, Int)` with something human-readable.
   * Add RULES pragma support
   * Add "SPECIALIZE instance" pragma support
   * Modify pretty printing of pragmas to follow GHC ppr indentation more
 closely.

 Here is a little demo:

 `HsToTh.hs`:
 {{{
 {-# LANGUAGE TemplateHaskell #-}

 module HsToTh (decls, hsToTh) where

 import Language.Haskell.TH

 decls = [d|
     f1 x = 1; f2 x = 2; f3 x = 3
     {-# INLINE f1 #-}
     {-# INLINE [2] f2 #-}
     {-# INLINE CONLIKE [~2] f3 #-}
     g1 x = 1; g2 x = 2; g3 x = 3
     {-# SPECIALISE g1 :: Int -> Int #-}
     {-# SPECIALISE [2] g2 :: Int -> Int #-}
     {-# SPECIALISE INLINE [~2] g3 :: Int -> Int #-}
     data T a = T a
     instance Eq a => Eq (T a) where
       {-# SPECIALISE instance Eq (T Int) #-}
       (T x) == (T y) = x == y
     {-# RULES
           "rule1" fromIntegral = id :: a -> a ;
           "rule2" [1] forall (x :: a) . fromIntegral x = x ;
           "rule3" [~1] forall (x :: a) . fromIntegral x = x
       #-}
   |]

 hsToTh = do
   decls' <- runQ decls
   mapM (print . ppr) decls'
 }}}
 `ThToHs.hs`:
 {{{
 {-# LANGUAGE TemplateHaskell #-}

 import HsToTh

 $(decls)

 main = hsToTh
 }}}
 TH -> Hs (actually Hs -> TH -> Hs):
 {{{
 $ ./Dev/ghc/inplace/bin/ghc-stage2 -dcore-lint -ddump-splices -fforce-
 recomp HsToTh.hs ThToHs.hs
 [1 of 2] Compiling HsToTh           ( HsToTh.hs, HsToTh.o )
 [2 of 2] Compiling Main             ( ThToHs.hs, ThToHs.o )
 Loading package ghc-prim ... linking ... done.
 Loading package integer-gmp ... linking ... done.
 Loading package base ... linking ... done.
 Loading package pretty-1.1.1.0 ... linking ... done.
 Loading package array-0.3.0.3 ... linking ... done.
 Loading package deepseq-1.2.0.1 ... linking ... done.
 Loading package containers-0.5.0.0 ... linking ... done.
 Loading package template-haskell ... linking ... done.
 ThToHs.hs:1:1: Splicing declarations
     decls
   ======>
     ThToHs.hs:5:3-7
     f1_a2rr x_a2ru = 1
     f2_a2rq x_a2rv = 2
     f3_a2rp x_a2rw = 3
     {-# INLINE f1_a2rr #-}
     {-# INLINE[2] f2_a2rq #-}
     {-# INLINE[~2] CONLIKE f3_a2rp #-}
     g1_a2ro x_a2rx = 1
     g2_a2rn x_a2ry = 2
     g3_a2rm x_a2rz = 3
     {-# SPECIALIZE g1_a2ro :: Int -> Int #-}
     {-# SPECIALIZE [2] g2_a2rn :: Int -> Int #-}
     {-# SPECIALIZE INLINE[~2] g3_a2rm :: Int -> Int #-}
     data T_a2rs a_a2rA = T_a2rt a_a2rA
     instance Eq a_a2rB => Eq (T_a2rs a_a2rB) where
       {-# SPECIALIZE instance Eq (T_a2rs Int) #-}
       == (T_a2rt x_a2rC) (T_a2rt y_a2rD) = (x_a2rC == y_a2rD)
     {-# RULES "rule1" [ALWAYS]
         fromIntegral
         = id :: forall a_a2rE. a_a2rE -> a_a2rE #-}
     {-# RULES "rule2" [1] forall x::a. fromIntegral x = x #-}
     {-# RULES "rule3" [~1] forall x::a. fromIntegral x = x #-}
 Linking ThToHs ...
 }}}
 Hs -> TH:
 {{{
 $ ./ThToHs
 f1_0 x_1 = 1
 f2_0 x_1 = 2
 f3_0 x_1 = 3
 {-# INLINE f1_0 #-}
 {-# INLINE [2] f2_0 #-}
 {-# INLINE CONLIKE [~2] f3_0 #-}
 g1_0 x_1 = 1
 g2_0 x_1 = 2
 g3_0 x_1 = 3
 {-# SPECIALISE g1_0 :: GHC.Types.Int -> GHC.Types.Int #-}
 {-# SPECIALISE [2] g2_0 :: GHC.Types.Int -> GHC.Types.Int #-}
 {-# SPECIALISE INLINE [~2] g3_0 ::
                              GHC.Types.Int -> GHC.Types.Int #-}
 data T_0 a_1 = T_2 a_1
 instance GHC.Classes.Eq a_0 => GHC.Classes.Eq (T_1 a_0)
     where GHC.Classes.== (T_2 x_3) (T_2 y_4) = x_3 GHC.Classes.== y_4
           {-# SPECIALISE instance GHC.Classes.Eq (T_1 GHC.Types.Int) #-}
 {-# RULES "rule1"
     GHC.Real.fromIntegral
     = GHC.Base.id :: forall a_0 . a_0 -> a_0 #-}
 {-# RULES "rule2" [1]
     forall (x_1627391595 :: a_1627391596) . GHC.Real.fromIntegral
 x_1627391595
     = x_1627391595 #-}
 {-# RULES "rule3" [~1]
     forall (x_1627391593 :: a_1627391594) . GHC.Real.fromIntegral
 x_1627391593
     = x_1627391593 #-}
 }}}
 Please review.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7064>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to