packages feed

jacinda-2.0.2.0: src/A/I.hs

{-# LANGUAGE FlexibleContexts #-}

module A.I ( RM, UM, ISt (..)
           , ib
           , β, lβ
           , runI
           ) where

import           A
import           Control.Monad.State.Strict (State, gets, modify, runState, state)
import           Data.Bifunctor             (second)
import           Data.Foldable              (traverse_)
import qualified Data.IntMap                as IM
import           Nm
import           R
import           Ty
import           U

data ISt a = ISt { renames :: !Renames
                 , binds   :: IM.IntMap (E a)
                 }

instance HasRenames (ISt a) where
    rename f s = fmap (\x -> s { renames = x }) (f (renames s))

type RM a = State (ISt a); type UM = State Int

bind :: Nm a -> E a -> ISt a -> ISt a
bind (Nm _ (U u) _) e (ISt r bs) = ISt r (IM.insert u e bs)

runI i = second (max_.renames) . flip runState (ISt (Renames i mempty) mempty)

ib :: Int -> Program T -> (E T, Int)
ib i = uncurry (flip β).runI i.iP where iP (Program ds e) = traverse_ iD ds *> iE e

β :: Int -> E a -> (E a, Int)
β i = runI i.bM.(i `seq`)

lβ :: E a -> UM (E a)
lβ e = state (`β` e)

iD :: D T -> RM T ()
iD (FunDecl n [] e) = do {eI <- iE e; modify (bind n eI)}
iD SetFS{} = pure (); iD SetRS{} = pure (); iD SetAsv = pure (); iD FlushDecl{} = pure ()
iD FunDecl{} = desugar

desugar = error "Internal error. Should have been de-sugared in an earlier stage!"

bM :: E a -> RM a (E a)
bM (EApp _ (EApp _ (Lam _ n (Lam _ n' e')) e'') e) = do
    eI <- bM e
    modify (bind n' eI)
    eI'' <- bM e''
    modify (bind n eI'')
    bM e'
bM (EApp _ (Lam _ n e') e) = do
    eI <- bM e
    modify (bind n eI) *> bM e'
bM (EApp l e0 e1) = do
    e0' <- bM e0
    e1' <- bM e1
    case e0' of
        Lam{} -> bM (EApp l e0' e1')
        _     -> pure (EApp l e0' e1')
bM e@(Var _ (Nm _ (U i) _)) = do
    st <- gets binds
    case IM.lookup i st of
        Just e' -> rE e'
        Nothing -> pure e
bM (Let l (n, e') e) = do
    e'B <- bM e'
    eB <- bM e
    pure $ Let l (n, e'B) eB
bM (Tup l es) = Tup l <$> traverse bM es; bM (Arr l es) = Arr l <$> traverse bM es
bM (Anchor l es) = Anchor l <$> traverse bM es; bM (OptionVal l es) = OptionVal l <$> traverse bM es
bM (Lam l n e) = Lam l n <$> bM e
bM (Implicit l e) = Implicit l <$> bM e
bM (Guarded l e0 e1) = Guarded l <$> bM e0 <*> bM e1
bM (Cond l p e0 e1) = Cond l <$> bM p <*> bM e0 <*> bM e1
bM e@Column{} = pure e; bM e@IParseCol{} = pure e; bM e@FParseCol{} = pure e; bM e@AllField{} = pure e
bM e@LastField{} = pure e; bM e@Field{} = pure e; bM e@FieldList{} = pure e; bM e@ParseCol{} = pure e
bM e@AllColumn{} = pure e; bM e@FParseAllCol{} = pure e; bM e@IParseAllCol{} = pure e; bM e@ParseAllCol{} = pure e
bM e@RC{} = pure e; bM e@Lit{} = pure e; bM e@RegexLit{} = pure e
bM e@BB{} = pure e; bM e@NB{} = pure e; bM e@UB{} = pure e; bM e@TB{} = pure e
bM ResVar{} = desugar; bM Dfn{} = desugar; bM Paren{} = desugar

iE :: E T -> RM T (E T)
iE e@NB{} = pure e; iE e@UB{} = pure e; iE e@BB{} = pure e; iE e@TB{} = pure e
iE e@Column{} = pure e; iE e@ParseCol{} = pure e; iE e@IParseCol{} = pure e; iE e@FParseCol{} = pure e
iE e@Field{} = pure e; iE e@LastField{} = pure e; iE e@AllField{} = pure e; iE e@FieldList{} = pure e
iE e@AllColumn{} = pure e; iE e@FParseAllCol{} = pure e; iE e@IParseAllCol{} = pure e; iE e@ParseAllCol{} = pure e
iE e@Lit{} = pure e
iE e@RegexLit{} = pure e; iE e@RC{} = pure e
iE (EApp t e e') = EApp t <$> iE e <*> iE e'
iE (Guarded t p e) = Guarded t <$> iE p <*> iE e
iE (Implicit t e) = Implicit t <$> iE e
iE (Lam t n e) = Lam t n <$> iE e
iE (Tup t es) = Tup t <$> traverse iE es
iE (Arr t es) = Arr t <$> traverse iE es
iE (Anchor t es) = Anchor t <$> traverse iE es
iE (OptionVal t es) = OptionVal t <$> traverse iE es
iE (Cond t p e e') = Cond t <$> iE p <*> iE e <*> iE e'
iE (Let _ (n, e') e) = do
    eI <- iE e'
    modify (bind n eI) *> iE e
iE e@(Var t (Nm _ (U i) _)) = do
    st <- gets binds
    case IM.lookup i st of
        Just e' -> do {er <- rE e'; pure $ fmap (aT (match (eLoc er) t)) er}
        Nothing -> pure e
iE Dfn{} = desugar; iE Paren{} = desugar; iE ResVar{} = desugar