jacinda-2.0.2.0: src/A/E.hs
{-# LANGUAGE OverloadedStrings #-}
module A.E ( M, nN, eta ) where
import A
import Control.Monad ((<=<))
import Control.Monad.State.Strict (State, state)
import qualified Data.Text as T
import Nm
import U
type M = State Int
nN :: T.Text -> a -> M (Nm a)
nN n l = state (\i -> (Nm n (U$i+1) l, i+1))
doms :: T -> [T]
doms (TyArr t t') = t:doms t'; doms _ = []
cLam :: E a -> Int
cLam (Lam _ _ e) = 1+cLam e; cLam _ = 0
tuck :: E a -> (E a -> E a, E a)
tuck (Lam l n e) = let (f, e') = tuck e in (Lam l n.f, e'); tuck e = (id, e)
unseam :: [T] -> M (E T -> E T, E T -> E T)
unseam ts = do
lApps <- traverse (\t -> do {n <- nN "x" t; pure (\e' -> let t' = eLoc e' in Lam (TyArr t t') n e', \e' -> let TyArr _ cod = eLoc e' in EApp cod e' (Var t n))}) ts
let (ls, eApps) = unzip lApps
pure (thread ls, thread (reverse eApps))
where thread = foldr (.) id
mkLam :: [T] -> E T -> M (E T)
mkLam ts e = do
(lam, app) <- unseam ts
pure $ lam (app e)
eta = eM <=< eO
eM :: E T -> M (E T)
eM (EApp t ho@(BB _ Map) op) = EApp t ho <$> eta op
eM (EApp t ho@(BB _ Filter) op) = EApp t ho <$> eta op
eM (EApp t ho@(BB _ Prior) op) = EApp t ho <$> eta op
eM (EApp t ho@(BB _ DedupOn) op) = EApp t ho <$> eta op
eM (EApp t ho@(BB _ Fold1) op) = EApp t ho <$> eta op
eM (EApp t ho@(TB _ Fold) op) = EApp t ho <$> eta op
eM (EApp t ho@(TB _ Scan) op) = EApp t ho <$> eta op
eM (EApp t ho@(TB _ ZipW) op) = EApp t ho <$> eta op
eM (EApp t e0 e1) = EApp t <$> eM e0 <*> eM e1
eM (Cond t p e0 e1) = Cond t <$> eM p <*> eM e0 <*> eM e1
eM (OptionVal t e) = OptionVal t <$> traverse eM e
eM (Implicit t e) = Implicit t <$> eM e
eM (Lam t n e) = Lam t n <$> eM e
eM (Guarded t p e) = Guarded t <$> eM p <*> eM e
eM (Tup t es) = Tup t <$> traverse eM es
eM (Anchor t es) = Anchor t <$> traverse eM es
eM (Arr t es) = Arr t <$> traverse eM es
eM (Let t (n, e') e) = do {e'๐ <- eM e'; e๐ <- eM e; pure (Let t (n, e'๐) e๐)}
eM e = pure e
-- outermost
eO :: E T -> M (E T)
eO e@(Var t@TyArr{} _) = mkLam (doms t) e
eO e@(UB t _) = mkLam (doms t) e
eO e@(BB t _) = mkLam (doms t) e
eO e@(TB t _) = mkLam (doms t) e
eO e@(EApp t@TyArr{} _ _) = mkLam (doms t) e
eO e@(Lam t@TyArr{} _ _) = do
let l = length (doms t)
(preL, e') = tuck e
(lam, app) <- unseam (take (l-cLam e) $ doms t)
pure (lam (preL (app e')))
eO e = pure e