monadic-bang-0.1.0.0: GHC plugin to desugar ! into do-notation
Safe HaskellSafe-Inferred
LanguageGHC2021

MonadicBang.Internal

Synopsis

Documentation

data Loc Source #

Constructors

MkLoc 

Fields

Instances

Instances details
Show Loc Source # 
Instance details

Defined in MonadicBang.Internal

Methods

showsPrec :: Int -> Loc -> ShowS #

show :: Loc -> String #

showList :: [Loc] -> ShowS #

Eq Loc Source # 
Instance details

Defined in MonadicBang.Internal

Methods

(==) :: Loc -> Loc -> Bool #

(/=) :: Loc -> Loc -> Bool #

Ord Loc Source # 
Instance details

Defined in MonadicBang.Internal

Methods

compare :: Loc -> Loc -> Ordering #

(<) :: Loc -> Loc -> Bool #

(<=) :: Loc -> Loc -> Bool #

(>) :: Loc -> Loc -> Bool #

(>=) :: Loc -> Loc -> Bool #

max :: Loc -> Loc -> Loc #

min :: Loc -> Loc -> Loc #

data InScope Source #

To keep track of which local variables in scope may be used

If local variables are defined within the same statement as a !, but outside of that !, they must not be used within this !, since their desugaring would make them escape their scope.

Constructors

MkInScope 

Fields

Instances

Instances details
Monoid InScope Source # 
Instance details

Defined in MonadicBang.Internal

Semigroup InScope Source # 
Instance details

Defined in MonadicBang.Internal

isInvalid :: Has (Reader InScope) sig m => OccName -> m Bool Source #

bangLoc :: Loc -> Loc Source #

Decrement column by one to get the location of a !

bangSpan :: SrcSpan -> SrcSpan Source #

Decrement start by one column to get the location of a !

bangSrcLoc :: SrcLoc -> SrcLoc Source #

Decrement column by one to get the location of a !

pattern ExprLoc :: Loc -> Expr -> LExpr Source #

Used to extract the Loc of a located expression

type family HandleFailure canFail = t | t -> canFail where ... Source #

class MonadTrans t => HandlingMonadTrans t where Source #

Methods

toMaybeT :: Monad m => t m a -> MaybeT m a Source #

Instances

Instances details
HandlingMonadTrans MaybeT Source # 
Instance details

Defined in MonadicBang.Internal

Methods

toMaybeT :: forall (m :: Type -> Type) a. Monad m => MaybeT m a -> MaybeT m a Source #

HandlingMonadTrans (IdentityT :: (Type -> Type) -> Type -> Type) Source # 
Instance details

Defined in MonadicBang.Internal

Methods

toMaybeT :: forall (m :: Type -> Type) a. Monad m => IdentityT m a -> MaybeT m a Source #

class Typeable (AstType a) => Handle a where Source #

Associated Types

type CanFail a :: Bool Source #

type AstType a = (r :: Type) | r -> a Source #

type Effects a :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall sig m m'. m ~ HandleFailure (CanFail a) m' => Has (Effects a) sig m' => Handler m (AstType a) Source #

Instances

Instances details
Handle StmtLR Source # 
Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail StmtLR :: Bool Source #

type AstType StmtLR = (r :: Type) Source #

type Effects StmtLR :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail StmtLR) m', Has (Effects StmtLR) sig m') => Handler m (AstType StmtLR) Source #

Handle HsBindLR Source #

We keep track of any local binds, to prevent the user from using them with ! in situations where they would be evacuated to a place where they're not in scope

The plugin would still work without this, but might accept programs that shouldn't be accepted, with unexpected semantics. E.g:

do let s = pure "outer"
   let s = pure "inner" in putStrLn !s

You might expect this to print inner, but it would actually print outer, since it would be desugared to

do let s = pure "outer"
   <!s> <- s
   let s = pure "inner" in print <!s>

With this function, the plugin will instead throw an error saying that s cannot be used here.

If the first s weren't defined, the user would, without this function, get an error saying that s is not in scope, at the call site. Here, we instead throw a more informative error.

If only the first s were defined, i.e.

do let s = pure "outer"
   putStrLn !s

it would be valid code.

Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail HsBindLR :: Bool Source #

type AstType HsBindLR = (r :: Type) Source #

type Effects HsBindLR :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail HsBindLR) m', Has (Effects HsBindLR) sig m') => Handler m (AstType HsBindLR) Source #

Handle GRHSs Source # 
Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail GRHSs :: Bool Source #

type AstType GRHSs = (r :: Type) Source #

type Effects GRHSs :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail GRHSs) m', Has (Effects GRHSs) sig m') => Handler m (AstType GRHSs) Source #

Handle Match Source # 
Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail Match :: Bool Source #

type AstType Match = (r :: Type) Source #

type Effects Match :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail Match) m', Has (Effects Match) sig m') => Handler m (AstType Match) Source #

Handle MatchGroup Source # 
Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail MatchGroup :: Bool Source #

type AstType MatchGroup = (r :: Type) Source #

type Effects MatchGroup :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail MatchGroup) m', Has (Effects MatchGroup) sig m') => Handler m (AstType MatchGroup) Source #

Handle HsExpr Source # 
Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail HsExpr :: Bool Source #

type AstType HsExpr = (r :: Type) Source #

type Effects HsExpr :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail HsExpr) m', Has (Effects HsExpr) sig m') => Handler m (AstType HsExpr) Source #

Handle Pat Source # 
Instance details

Defined in MonadicBang.Internal

Associated Types

type CanFail Pat :: Bool Source #

type AstType Pat = (r :: Type) Source #

type Effects Pat :: (Type -> Type) -> Type -> Type Source #

Methods

handle' :: forall (sig :: (Type -> Type) -> Type -> Type) m (m' :: Type -> Type). (m ~ HandleFailure (CanFail Pat) m', Has (Effects Pat) sig m') => Handler m (AstType Pat) Source #

handle :: forall a sig m. (Handle a, CanFail a ~ False) => Has (Effects a) sig m => Handler m (AstType a) Source #

try :: forall e sig m a. (HandlingMonadTrans (HandleFailure (CanFail e)), Typeable a, Handle e, Monad m, Has (Effects e) sig m) => Try m a Source #

fillHoles :: (Data a, Has (PsErrors :+: (Reader Options :+: (Uniques :+: (LocalVars :+: Reader DynFlags)))) sig m) => Map Loc LExpr -> Handler m a Source #

Replace holes in an AST whenever an expression with the corresponding source span can be found in the given list.

evac :: forall a sig m. (Has Fill sig m, Data a) => Handler m a Source #

tryEvac :: Monad m => [Try m a] -> Try m a Source #

usualTries :: (Has Fill sig m, Data a) => [Try m a] Source #

ignore :: forall (e :: Type) m a. (Monad m, Typeable a, Typeable e) => Try m a Source #

evacPats :: forall a m sig. (Has (Fill :+: State InScope) sig m, Data a) => Handler m a Source #

evacuate !s in pattern and collect all the names it binds

addStmts :: forall sig m. Has (PsErrors :+: (HoleFills :+: (Uniques :+: (LocalVars :+: Reader DynFlags)))) sig m => Handler m [ExprLStmt GhcPs] Source #

Find all !s in the given statements and combine the resulting bind statements into lists, with the original statements being the last one in each list - then concatenate these lists

type LocalVars = Reader InScope :+: Writer OccSet Source #

We keep track of variables that are bound in lambdas, cases, etc., since these are variables that will not be accessible in the surrounding 'do'-block, and must therefore not be used. The Reader is used to find out what local variables are in scope, the Writer is used to inform callers which local variables have been bound.

type Fill = PsErrors :+: (Writer (DList BindStmt) :+: (HoleFills :+: (Uniques :+: (LocalVars :+: Reader DynFlags)))) Source #

data BindStmt Source #

Constructors

RdrName :<- LExpr 

bangVar :: Has (Uniques :+: Reader DynFlags) sig m => LExpr -> Loc -> m RdrName Source #

Use the !'d expression if it's short enough, or else abbreviate with ... We don't need to worry about shadowing other !'d expressions: - For the user, we add line and column numbers to the name - For the compiler, we use a unique instead of the name

locVar :: Has Uniques sig m => String -> SrcSpan -> Loc -> m RdrName Source #

tellOne :: Has (Writer (DList w)) sig m => w -> m () Source #

tellLocalVar :: Has (Writer OccSet) sig m => OccName -> m () Source #