{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Ormolu.Printer.Meat.Declaration.Foreign
  ( p_foreignDecl,
  )
where

import Control.Monad
import GHC.Hs
import GHC.Types.ForeignCall
import GHC.Types.SrcLoc
import Ormolu.Printer.Combinators
import Ormolu.Printer.Meat.Common
import Ormolu.Printer.Meat.Declaration.Signature

p_foreignDecl :: ForeignDecl GhcPs -> R ()
p_foreignDecl :: ForeignDecl GhcPs -> R ()
p_foreignDecl = \case
  fd :: ForeignDecl GhcPs
fd@ForeignImport {ForeignImport GhcPs
fd_fi :: ForeignImport GhcPs
fd_fi :: forall pass. ForeignDecl pass -> ForeignImport pass
fd_fi} -> do
    ForeignImport GhcPs -> R ()
p_foreignImport ForeignImport GhcPs
fd_fi
    ForeignDecl GhcPs -> R ()
p_foreignTypeSig ForeignDecl GhcPs
fd
  fd :: ForeignDecl GhcPs
fd@ForeignExport {ForeignExport GhcPs
fd_fe :: ForeignExport GhcPs
fd_fe :: forall pass. ForeignDecl pass -> ForeignExport pass
fd_fe} -> do
    ForeignExport GhcPs -> R ()
p_foreignExport ForeignExport GhcPs
fd_fe
    ForeignDecl GhcPs -> R ()
p_foreignTypeSig ForeignDecl GhcPs
fd

-- | Printer for the last part of an import\/export, which is function name
-- and type signature.
p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
p_foreignTypeSig ForeignDecl GhcPs
fd = do
  R ()
breakpoint
  R () -> R ()
inci
    (R () -> R ()) -> (R () -> R ()) -> R () -> R ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SrcSpan] -> R () -> R ()
switchLayout
      [ GenLocated (SrcSpanAnn' (EpAnn NameAnn)) RdrName -> SrcSpan
forall a e. GenLocated (SrcSpanAnn' a) e -> SrcSpan
getLocA (ForeignDecl GhcPs -> LIdP GhcPs
forall pass. ForeignDecl pass -> LIdP pass
fd_name ForeignDecl GhcPs
fd),
        (GenLocated (SrcSpanAnn' (EpAnn AnnListItem)) (HsSigType GhcPs)
-> SrcSpan
forall a e. GenLocated (SrcSpanAnn' a) e -> SrcSpan
getLocA (GenLocated (SrcSpanAnn' (EpAnn AnnListItem)) (HsSigType GhcPs)
 -> SrcSpan)
-> (ForeignDecl GhcPs
    -> GenLocated (SrcSpanAnn' (EpAnn AnnListItem)) (HsSigType GhcPs))
-> ForeignDecl GhcPs
-> SrcSpan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignDecl GhcPs -> LHsSigType GhcPs
ForeignDecl GhcPs
-> GenLocated (SrcSpanAnn' (EpAnn AnnListItem)) (HsSigType GhcPs)
forall pass. ForeignDecl pass -> LHsSigType pass
fd_sig_ty) ForeignDecl GhcPs
fd
      ]
    (R () -> R ()) -> R () -> R ()
forall a b. (a -> b) -> a -> b
$ do
      GenLocated (SrcSpanAnn' (EpAnn NameAnn)) RdrName -> R ()
p_rdrName (ForeignDecl GhcPs -> LIdP GhcPs
forall pass. ForeignDecl pass -> LIdP pass
fd_name ForeignDecl GhcPs
fd)
      LHsSigType GhcPs -> R ()
p_typeAscription (ForeignDecl GhcPs -> LHsSigType GhcPs
forall pass. ForeignDecl pass -> LHsSigType pass
fd_sig_ty ForeignDecl GhcPs
fd)

-- | Printer for 'ForeignImport'.
--
-- These have the form:
--
-- > foreign import callingConvention [safety] [identifier]
--
-- We need to check whether the safety has a good source, span, as it
-- defaults to 'PlaySafe' if you don't have anything in the source.
--
-- We also layout the identifier using the 'SourceText', because printing
-- with the other two fields of 'CImport' is very complicated. See the
-- 'Outputable' instance of 'ForeignImport' for details.
p_foreignImport :: ForeignImport GhcPs -> R ()
p_foreignImport :: ForeignImport GhcPs -> R ()
p_foreignImport (CImport XCImport GhcPs
sourceText XRec GhcPs CCallConv
cCallConv XRec GhcPs Safety
safety Maybe Header
_ CImportSpec
_) = do
  Text -> R ()
txt Text
"foreign import"
  R ()
space
  GenLocated SrcSpan CCallConv -> (CCallConv -> R ()) -> R ()
forall l a. HasSrcSpan l => GenLocated l a -> (a -> R ()) -> R ()
located XRec GhcPs CCallConv
GenLocated SrcSpan CCallConv
cCallConv CCallConv -> R ()
forall a. Outputable a => a -> R ()
atom
  -- Need to check for 'noLoc' for the 'safe' annotation
  Bool -> R () -> R ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SrcSpan -> Bool
isGoodSrcSpan (SrcSpan -> Bool) -> SrcSpan -> Bool
forall a b. (a -> b) -> a -> b
$ GenLocated SrcSpan Safety -> SrcSpan
forall l e. GenLocated l e -> l
getLoc XRec GhcPs Safety
GenLocated SrcSpan Safety
safety) (R ()
space R () -> R () -> R ()
forall a b. R a -> R b -> R b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> GenLocated SrcSpan Safety -> R ()
forall a. Outputable a => a -> R ()
atom XRec GhcPs Safety
GenLocated SrcSpan Safety
safety)
  R ()
space
  GenLocated SrcSpan SourceText -> (SourceText -> R ()) -> R ()
forall l a. HasSrcSpan l => GenLocated l a -> (a -> R ()) -> R ()
located XCImport GhcPs
GenLocated SrcSpan SourceText
sourceText SourceText -> R ()
p_sourceText

p_foreignExport :: ForeignExport GhcPs -> R ()
p_foreignExport :: ForeignExport GhcPs -> R ()
p_foreignExport (CExport XCExport GhcPs
sourceText (L SrcSpan
loc (CExportStatic SourceText
_ CLabelString
_ CCallConv
cCallConv))) = do
  Text -> R ()
txt Text
"foreign export"
  R ()
space
  GenLocated SrcSpan CCallConv -> (CCallConv -> R ()) -> R ()
forall l a. HasSrcSpan l => GenLocated l a -> (a -> R ()) -> R ()
located (SrcSpan -> CCallConv -> GenLocated SrcSpan CCallConv
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc CCallConv
cCallConv) CCallConv -> R ()
forall a. Outputable a => a -> R ()
atom
  R ()
space
  GenLocated SrcSpan SourceText -> (SourceText -> R ()) -> R ()
forall l a. HasSrcSpan l => GenLocated l a -> (a -> R ()) -> R ()
located XCExport GhcPs
GenLocated SrcSpan SourceText
sourceText SourceText -> R ()
p_sourceText