packages feed

ide-backend-server-0.9.0: GhcShim/API.hs

{-# LANGUAGE MultiParamTypeClasses, GADTs, FlexibleInstances #-}
module GhcShim.API (
    -- * Traversing the AST
    IsBinder(..)
  , AstAlg(..)
  , Fold(..)
  , FoldPhase(..)
  ) where

import Type   (Type)
import SrcLoc (SrcSpan, Located)
import Name   (Name)
import Var    (Var)

-- | Is this a binding occurrence of @f@?
data IsBinder =
    DefSite   -- ^ @f = ..@
  | UseSite   -- ^ @g = f ..@
  | SigSite   -- ^ @f :: ..@ or fixity declaration

-- | The "algebra" that we use while traversing the AST.
--
-- This is not a general purpose fold; we look for identifiers and types.
data AstAlg m id = AstAlg {
    -- | Mark a branch point in the AST
    astMark :: Maybe SrcSpan -> String -> m (Maybe Type) -> m (Maybe Type)
    -- | Throw a runtime error
  , astUnsupported :: Maybe SrcSpan -> String -> m (Maybe Type)
    -- | Found a subexpression type
  , astExpType :: SrcSpan -> Maybe Type -> m (Maybe Type)
    -- | Found a 'Name' (i.e., pre type checking)
  , astId :: IsBinder -> Located id -> m (Maybe Type)
    -- | Are we running pre or post type checking?
  , astPhase :: FoldPhase id
  }

class Fold id a where
  fold :: Monad m => AstAlg m id -> a -> m (Maybe Type)

data FoldPhase id where
  FoldPreTc  :: FoldPhase Name
  FoldPostTc :: FoldPhase Var

instance Fold id a => Fold id [a] where
  fold alg xs = do
    mapM_ (fold alg) xs
    return Nothing

instance Fold id a => Fold id (Maybe a) where
  fold _alg Nothing  = return Nothing
  fold  alg (Just x) = fold alg x