diff options
Diffstat (limited to 'libraries/template-haskell/Language/Haskell/TH/Syntax.hs')
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Syntax.hs | 159 |
1 files changed, 108 insertions, 51 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs index a894ce8378..dac97c641f 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs @@ -374,6 +374,63 @@ be inferred (#8459). Consider The splice will evaluate to (MkAge 3) and you can't add that to 4::Int. So you can't coerce a (TExp Age) to a (TExp Int). -} +-- Code constructor + +type role Code representational nominal -- See Note [Role of TExp] +newtype Code m (a :: TYPE (r :: RuntimeRep)) = Code + { examineCode :: m (TExp a) -- ^ Underlying monadic value + } + +-- | Unsafely convert an untyped code representation into a typed code +-- representation. +unsafeCodeCoerce :: forall (r :: RuntimeRep) (a :: TYPE r) m . + Quote m => m Exp -> Code m a +unsafeCodeCoerce m = Code (unsafeTExpCoerce m) + +-- | Lift a monadic action producing code into the typed 'Code' +-- representation +liftCode :: forall (r :: RuntimeRep) (a :: TYPE r) m . m (TExp a) -> Code m a +liftCode = Code + +-- | Extract the untyped representation from the typed representation +unTypeCode :: forall (r :: RuntimeRep) (a :: TYPE r) m . Quote m + => Code m a -> m Exp +unTypeCode = unTypeQ . examineCode + +-- | Modify the ambient monad used during code generation. For example, you +-- can use `hoistCode` to handle a state effect: +-- @ +-- handleState :: Code (StateT Int Q) a -> Code Q a +-- handleState = hoistCode (flip runState 0) +-- @ +hoistCode :: forall m n (r :: RuntimeRep) (a :: TYPE r) . Monad m + => (forall x . m x -> n x) -> Code m a -> Code n a +hoistCode f (Code a) = Code (f a) + + +-- | Variant of (>>=) which allows effectful computations to be injected +-- into code generation. +bindCode :: forall m a (r :: RuntimeRep) (b :: TYPE r) . Monad m + => m a -> (a -> Code m b) -> Code m b +bindCode q k = liftCode (q >>= examineCode . k) + +-- | Variant of (>>) which allows effectful computations to be injected +-- into code generation. +bindCode_ :: forall m a (r :: RuntimeRep) (b :: TYPE r) . Monad m + => m a -> Code m b -> Code m b +bindCode_ q c = liftCode ( q >> examineCode c) + +-- | A useful combinator for embedding monadic actions into 'Code' +-- @ +-- myCode :: ... => Code m a +-- myCode = joinCode $ do +-- x <- someSideEffect +-- return (makeCodeWith x) +-- @ +joinCode :: forall m (r :: RuntimeRep) (a :: TYPE r) . Monad m + => m (Code m a) -> Code m a +joinCode = flip bindCode id + ---------------------------------------------------- -- Packaged versions for the programmer, hiding the Quasi-ness @@ -758,107 +815,107 @@ class Lift (t :: TYPE r) where -- a splice. lift :: Quote m => t -> m Exp default lift :: (r ~ 'LiftedRep, Quote m) => t -> m Exp - lift = unTypeQ . liftTyped + lift = unTypeCode . liftTyped -- | Turn a value into a Template Haskell typed expression, suitable for use -- in a typed splice. -- -- @since 2.16.0.0 - liftTyped :: Quote m => t -> m (TExp t) + liftTyped :: Quote m => t -> Code m t -- If you add any instances here, consider updating test th/TH_Lift instance Lift Integer where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL x)) instance Lift Int where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) -- | @since 2.16.0.0 instance Lift Int# where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntPrimL (fromIntegral (I# x)))) instance Lift Int8 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Int16 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Int32 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Int64 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) -- | @since 2.16.0.0 instance Lift Word# where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (WordPrimL (fromIntegral (W# x)))) instance Lift Word where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Word8 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Word16 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Word32 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Word64 where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Lift Natural where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (IntegerL (fromIntegral x))) instance Integral a => Lift (Ratio a) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (RationalL (toRational x))) instance Lift Float where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (RationalL (toRational x))) -- | @since 2.16.0.0 instance Lift Float# where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (FloatPrimL (toRational (F# x)))) instance Lift Double where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (RationalL (toRational x))) -- | @since 2.16.0.0 instance Lift Double# where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (DoublePrimL (toRational (D# x)))) instance Lift Char where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (CharL x)) -- | @since 2.16.0.0 instance Lift Char# where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (CharPrimL (C# x))) instance Lift Bool where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift True = return (ConE trueName) lift False = return (ConE falseName) @@ -868,24 +925,24 @@ instance Lift Bool where -- -- @since 2.16.0.0 instance Lift Addr# where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = return (LitE (StringPrimL (map (fromIntegral . ord) (unpackCString# x)))) instance Lift a => Lift (Maybe a) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift Nothing = return (ConE nothingName) lift (Just x) = liftM (ConE justName `AppE`) (lift x) instance (Lift a, Lift b) => Lift (Either a b) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (Left x) = liftM (ConE leftName `AppE`) (lift x) lift (Right y) = liftM (ConE rightName `AppE`) (lift y) instance Lift a => Lift [a] where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift xs = do { xs' <- mapM lift xs; return (ListE xs') } liftString :: Quote m => String -> m Exp @@ -894,7 +951,7 @@ liftString s = return (LitE (StringL s)) -- | @since 2.15.0.0 instance Lift a => Lift (NonEmpty a) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (x :| xs) = do x' <- lift x @@ -903,77 +960,77 @@ instance Lift a => Lift (NonEmpty a) where -- | @since 2.15.0.0 instance Lift Void where - liftTyped = pure . absurd + liftTyped = liftCode . absurd lift = pure . absurd instance Lift () where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift () = return (ConE (tupleDataName 0)) instance (Lift a, Lift b) => Lift (a, b) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (a, b) = liftM TupE $ sequence $ map (fmap Just) [lift a, lift b] instance (Lift a, Lift b, Lift c) => Lift (a, b, c) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (a, b, c) = liftM TupE $ sequence $ map (fmap Just) [lift a, lift b, lift c] instance (Lift a, Lift b, Lift c, Lift d) => Lift (a, b, c, d) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (a, b, c, d) = liftM TupE $ sequence $ map (fmap Just) [lift a, lift b, lift c, lift d] instance (Lift a, Lift b, Lift c, Lift d, Lift e) => Lift (a, b, c, d, e) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (a, b, c, d, e) = liftM TupE $ sequence $ map (fmap Just) [ lift a, lift b , lift c, lift d, lift e ] instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift (a, b, c, d, e, f) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (a, b, c, d, e, f) = liftM TupE $ sequence $ map (fmap Just) [ lift a, lift b, lift c , lift d, lift e, lift f ] instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift (a, b, c, d, e, f, g) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (a, b, c, d, e, f, g) = liftM TupE $ sequence $ map (fmap Just) [ lift a, lift b, lift c , lift d, lift e, lift f, lift g ] -- | @since 2.16.0.0 instance Lift (# #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# #) = return (ConE (unboxedTupleTypeName 0)) -- | @since 2.16.0.0 instance (Lift a) => Lift (# a #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [lift a] -- | @since 2.16.0.0 instance (Lift a, Lift b) => Lift (# a, b #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a, b #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [lift a, lift b] -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c) => Lift (# a, b, c #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a, b, c #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [lift a, lift b, lift c] -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d) => Lift (# a, b, c, d #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a, b, c, d #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [ lift a, lift b , lift c, lift d ] @@ -981,7 +1038,7 @@ instance (Lift a, Lift b, Lift c, Lift d) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d, Lift e) => Lift (# a, b, c, d, e #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a, b, c, d, e #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [ lift a, lift b , lift c, lift d, lift e ] @@ -989,7 +1046,7 @@ instance (Lift a, Lift b, Lift c, Lift d, Lift e) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift (# a, b, c, d, e, f #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a, b, c, d, e, f #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [ lift a, lift b, lift c , lift d, lift e, lift f ] @@ -997,7 +1054,7 @@ instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift (# a, b, c, d, e, f, g #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift (# a, b, c, d, e, f, g #) = liftM UnboxedTupE $ sequence $ map (fmap Just) [ lift a, lift b, lift c , lift d, lift e, lift f @@ -1005,7 +1062,7 @@ instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) -- | @since 2.16.0.0 instance (Lift a, Lift b) => Lift (# a | b #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = case x of (# y | #) -> UnboxedSumE <$> lift y <*> pure 1 <*> pure 2 @@ -1014,7 +1071,7 @@ instance (Lift a, Lift b) => Lift (# a | b #) where -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c) => Lift (# a | b | c #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = case x of (# y | | #) -> UnboxedSumE <$> lift y <*> pure 1 <*> pure 3 @@ -1024,7 +1081,7 @@ instance (Lift a, Lift b, Lift c) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d) => Lift (# a | b | c | d #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = case x of (# y | | | #) -> UnboxedSumE <$> lift y <*> pure 1 <*> pure 4 @@ -1035,7 +1092,7 @@ instance (Lift a, Lift b, Lift c, Lift d) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d, Lift e) => Lift (# a | b | c | d | e #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = case x of (# y | | | | #) -> UnboxedSumE <$> lift y <*> pure 1 <*> pure 5 @@ -1047,7 +1104,7 @@ instance (Lift a, Lift b, Lift c, Lift d, Lift e) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift (# a | b | c | d | e | f #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = case x of (# y | | | | | #) -> UnboxedSumE <$> lift y <*> pure 1 <*> pure 6 @@ -1060,7 +1117,7 @@ instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) -- | @since 2.16.0.0 instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift (# a | b | c | d | e | f | g #) where - liftTyped x = unsafeTExpCoerce (lift x) + liftTyped x = unsafeCodeCoerce (lift x) lift x = case x of (# y | | | | | | #) -> UnboxedSumE <$> lift y <*> pure 1 <*> pure 7 |