> {-# OPTIONS_GHC -F -pgmF she #-} > {-# LANGUAGE TypeOperators, GADTs, TypeSynonymInstances, KindSignatures, > FlexibleInstances, GeneralizedNewtypeDeriving, TupleSections, > MultiParamTypeClasses #-} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > module Elab where %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > import Debug.Trace > import Prelude hiding (elem, all, foldr, concat) > import Data.Char > import Data.List hiding (elem, all, foldr, concat) > import Data.Monoid > import Data.Foldable > import Data.Traversable > import Control.Applicative > import Control.Monad > import Control.Newtype > import Control.Arrow > import Data.Void > import Gubbins > import Types > import Pa > import Syntax > import ElabMonad > import Unify > import Template > import Check %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% Cooked Terms %%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > data PAT > = PV String > | PC Template [PAT] -- void pattern is |PC [] []| > | PL Char -- char literal > | PR PAT > | PO Template [PAT] PAT -- op params continuation > instance Show PAT where > show (PV x) = x > show (PC t ps) = tempShow t (map show ps) > show (PR p) = "[" ++ show p ++ "]" > show (PO t ps p) = > "[" ++ tempShow t (map show ps) ++ " ? " ++ show p ++ "]" > data Dir > = CHK > | SYN > data TM :: {Dir} -> * where > H :: HD -> TM {SYN} > (:/) :: TM {SYN} -> [TM {CHK}] -> TM {SYN} > PApp :: TM {SYN} -> [TM {CHK}] -> TM {SYN} > HAN :: TM {SYN} -> TM {CHK} -> TM {SYN} > > E :: TM {SYN} -> TM {CHK} > CL :: Char -> TM {CHK} > CN :: Template -> [TM {CHK}] -> TM {CHK} > BUNK :: TM {CHK} -> TM {CHK} > LAM :: [([PAT], TM {CHK})] -> TM {CHK} > data HD = VA Int > | FN Template -- cache the def like a Birdman? > | OP Template > hTemp :: Bwd Entry -> HD -> Template > hTemp g (VA i) = fst (inx g i) > hTemp g (FN f) = f > hTemp g (OP o) = o > gShow :: Bwd Entry -> TM {d} -> String > gShow g (H h) = tempShow x ["_" | Place <- x] where x = hTemp g h > gShow g (f :/ []) = gShow g f ++ " !" > gShow g (H h :/ ts) = tempShow (hTemp g h) (map (gShow g) ts) > gShow g (f :/ ts) = "(" ++ show f ++ (ts >>= ((' ' :) . show)) ++ ")" > gShow g (PApp f ts) = "(" ++ show f ++ (ts >>= ((' ' :) . show)) ++ ")" > gShow g (HAN h e) = "(" ++ gShow g h ++ "?" ++ gShow g e ++ ")" > gShow g (E t) = gShow g t > gShow g (CN c ts) = tempShow c (map (gShow g) ts) > gShow g (BUNK t) = "(" ++ gShow g t ++ " {})" > gShow g (LAM (a : as)) = > "{" ++ lShow a ++ (as >>= ((" | " ++) . lShow)) ++ "}" where > lShow ([], t) = gShow g t > lShow (ps, t) = > intercalate " " (map show ps) ++ " -> " ++ gShow (patOn g ps) t > patOn g [] = g > patOn g (PV x : ps) = patOn (bind g x) ps > patOn g (PC _ ps : ps') = patOn (patOn g ps) ps' > bind g x = g :< ([Mark x] ::: (0, Un)) -- cheeky! > inx :: Bwd Entry -> Int -> (Template, (Int, VT)) > inx (_ :< (x ::: (i, j))) 0 = (x, (i, j)) > inx (g :< (_ ::: _)) i = inx g (i - 1) > inx (g :< _) i = inx g i > inx B0 i = ([Mark ('#' : show i)], (0, Un)) > instance Show (TM {d}) where > show t = gShow B0 t %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% Type Checking and Synthesis %%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > checkR :: VT -> Raw -> ElabM (TM {CHK}) > --checkR v r | trace ("checkR " ++ show (v, r)) $ False = undefined > checkR v r = hnf v >>= \ v -> err (Raw v r) $ case r of > RVd -> (|(CN [] []) (-Un =?= v-)|) > RCh c -> (|(CL c) (-char =?= v-)|) > RTh prs -> case v of > U c -> (|LAM (traverse (body c) prs)|) > _ -> moanE $ GuessThunk prs > RN n -> checkR v (RA [RN n]) > RBunk -> moanE BadBunk > RA rs -> (|ttrCh ~v (|rawTree ~rs ~[] @ |) @ |) > RQ h e -> do > ss <- getSigsE > (h, z) <- synR h > z <- hnf z > case z of > U (M hs is u :-> F os w) -> do > w =?= v > canDo os > e <- withSigs (sAct hs ss) $ do > canDo is > checkR u e > (|(E (HAN h e))|) > _ -> moanE $ BadHandlerType z > r -> synR r >>= want v > synR :: Raw -> ElabM (TM {SYN}, VT) > --synR r | trace ("synR " ++ show r) $ False = undefined > synR (RN n) = synR (RA [RN n]) > synR RVd = moanE SynCon > synR RBunk = moanE BadBunk > synR (RA rs) = rawTree rs [] >>= \ t -> case t of > TNode f ts -> appSyn f ts > TLeaf r ts -> synR r >>= \ tv -> mention tv ts > synR (RTh prs) = moanE $ GuessThunk prs > synR (RQ h e) = do > ss <- getSigsE > (h, v) <- synR h > v <- hnf v > case v of > U (M hs is u :-> F os w) -> do > canDo os > e <- withSigs (sAct hs ss) $ do > canDo is > checkR u e > (|(HAN h e, w)|) > _ -> moanE $ BadHandlerType v > isBunk :: TTree Raw -> Bool > isBunk (TLeaf RBunk []) = True > isBunk _ = False > ttrCh :: VT -> (TTree Raw) -> ElabM (TM {CHK}) > --ttrCh v t | trace ("ttrCh " ++ show (v, t)) $ False = undefined > ttrCh v (TNode f ts) = if (not (null ts) && isBunk (last ts)) > then (|BUNK (ttrCh Ze (TNode f (init ts)))|) else do > info <- getInfoE > (g, _) <- getCxE > let constrs = [ (c, ((u, i), vs)) > | (u, (i , cs)) <- dataDecls info > , (c, vs) <- cs > ] > v <- hnf v > case v of > D u vs -> case lookup u (dataDecls info) of > Nothing -> moanE $ TMissing u > Just (i, cs) -> case lookup f cs of > Just ws -> (|(CN f) (ttrsCh f (xsub vs ws) ts)|) > Nothing -> appSyn f ts >>= want v > Q _ -> case (gFetch g f, filter ((f ==) . fst) constrs) of > (Nothing, [(_, ((u, m), vs))]) -> do > ws <- fresh m > ts <- ttrsCh f (xsub ws vs) ts > D u ws =?= v > (|(CN f ts)|) > _ -> appSyn f ts >>= want v > _ -> appSyn f ts >>= want v > ttrCh v (TLeaf r []) = checkR v r > ttrCh v _ = moanE $ Cockup "oops" > want :: VT -> (TM {SYN}, VT) -> ElabM (TM {CHK}) > want v (t, u) = (|(E t) (-u =?= v-)|) > getOps :: [Sig] -> ElabM [(Template, ([VT], (Sig, VT)))] > getOps [] = return [] > getOps (Pure : _) = return [] > getOps (s@(u :$ vs) : ss) = do > info <- getInfoE > (| ~[ (ot, xsub vs (ois, (s, oo))) > | (u', (i, os)) <- sigDecls info, u == u' > , (ot, (ois, oo)) <- os > ] ++ getOps ss |) > mkOpType :: [Sig] -> ([VT], (Sig, VT)) -> VT > mkOpType ss (vs, (s, v)) = sAct (U (foldr (:->) (F [s] v) vs)) ss > appSyn :: Template -> [TTree Raw] -> ElabM (TM {SYN}, VT) > --appSyn f ts | trace ("appSyn " ++ show (f, ts)) $ False = undefined > appSyn f ts = do > info <- getInfoE > sigs <- getSigsE > ops <- (|(map (id *** mkOpType sigs)) (getOps sigs)|) > (g, _) <- getCxE > case gFetch g f of > Just (i, (m, v)) -> do > ws <- fresh m > let v' = xsub ws v > --False <- trace ("FOUND: " ++ show f ++ " : " ++ show v') $ > -- return False > mention (H (VA i), xsub ws v) ts > Nothing -> case [v | (f', v) <- ops, f == f'] of > (_:_:_) -> moanE $ AmbiguousOp f sigs > [v] -> mention (H (OP f), v) ts > [] -> case lookup f (funDecls info) of > Just (m, vs, sa, v) -> do > ws <- fresh m > mention (H (FN f), > sAct (xsub ws (U (foldr (:->) (F sa v) vs))) sigs) > ts > Nothing -> moanE $ Dunno f sigs (foldMap gnom g) > gnom :: Entry -> [Template] > gnom (x ::: _) = [x] > gnom _ = [] > mention :: (TM {SYN}, VT) -> [TTree Raw] -> ElabM (TM {SYN}, VT) > mention tv [] = return tv > mention (t, U c) ts = use t [] c ts > mention (t, v) ts = moanE $ Useless v > use :: TM {SYN} -> [TM {CHK}] -> CT -> [TTree Raw] -> ElabM (TM {SYN}, VT) > use f [] (F ss v) (TLeaf RBang [] : ts) = do > canDo ss > mention (f :/ [], v) ts > use f as (F ss v) ts = do > canDo ss > mention (f :/ as, v) ts > use f as (v :-> c) (t : ts) = do > a <- ttrCh v t > use f (as ++ [a]) c ts > use f as c [] = (|(PApp f as, U c)|) > canDo :: [Sig] -> ElabM () > canDo [] = return () > canDo (s : ss) = do > ss' <- getSigsE > findSig s ss' ss' > canDo ss > findSig :: Sig -> [Sig] -> [Sig] -> ElabM () > findSig s [] sd = moanE $ CantDo s sd > findSig s@(a :$ us) ((b :$ vs) : ss) sd > | a == b = us =?= vs > | otherwise = findSig s ss sd > gFetch :: Bwd Entry -> Template -> Maybe (Int, (Int, VT)) > gFetch B0 _ = Nothing > gFetch (g :< (x ::: r)) y > | x == y = Just (0, r) > | otherwise = (|((1 +) *** id) (gFetch g y)|) > gFetch (g :< _) y = gFetch g y > fresh :: Int -> ElabM [VT] > fresh m = do > (g, n) <- getCxE > setCxE (grow g n m) > return (map Q (take m [n ..])) > where > grow g n 0 = (g, n) > grow g n m = grow (g :< (n :=? Nothing)) (n + 1) (m - 1) > ttrsCh :: Template -> [VT] -> [TTree Raw] -> ElabM [TM {CHK}] > ttrsCh f [] [] = return [] > ttrsCh f (v : vs) (t : ts) = (|ttrCh v t : ttrsCh f vs ts|) > ttrsCh f _ _ = moanE $ RawArityError f > body :: CT -> ([Pat], Raw) -> ElabM ([PAT], TM {CHK}) > body (v :-> c) (p : ps, r) = do > v <- hnf v > (g, p) <- patCh v p > (ps, t) <- cxLocal g $ body c (ps, r) > return (p : ps, t) > body (F ss v) ([], r) = do > t <- withSigs ss (checkR v r) > return ([], t) > body c (ps, r) = moanE $ ThunkMismatch c (ps, r) > rawTree :: [Raw] -> [TTree Raw] -> ElabM (TTree Raw) > rawTree rs ts = do > tbl <- ttT > case pa (resolve tbl) (map (rawPunc tbl) rs) of > [(t, [])] -> case t of > TLeaf (RA rs) ts -> rawTree rs ts > t -> return (tApp t ts) > _ -> moanE $ AmbiguousRaws rs > where > rawPunc tbl (RN x) | punc tbl x = Left x > rawPunc tbl p = Right p %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% Pattern Checking %%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > patCh :: VT -> Pat -> ElabM (Bwd Entry, PAT) > patCh v (PN x) = do > info <- getInfoE > if elem [Mark x] (ttTemplates (templateT info)) > then ttpCh v (TNode [Mark x] []) > else (|(B0 :< ([Mark x] ::: (0, v)), PV x)|) > patCh Un PVd = (|(B0, PC [] [])|) > patCh (D (Up "Char") []) (PCh c) = (|(B0, PL c)|) > patCh (M os ss v) (PRet p) = (|(id *** PR) (patCh v p)|) > patCh (M os ss v) (POp ps p) = patTree ps [] >>= \ z -> case z of > TLeaf p _ -> moanE $ BadMessPat ps > TNode o ts -> do > ops <- getOps os > case [x | (o', x) <- ops, o == o'] of > [(us, (s, u))] -> do > (gz, ps) <- ttpsCh o us ts > (hz, p) <- patCh (U (u :-> F (sAct os ss) v)) p > (|disjoin gz hz, ~(PO o ps p)|) > patCh v (PA ps) = patTree ps [] >>= ttpCh v > patCh v p = moanE $ BadPat v p > ttpCh :: VT -> TTree Pat -> ElabM (Bwd Entry, PAT) > ttpCh v (TLeaf p []) = patCh v p > ttpCh v (TLeaf (PN n) _) = moanE $ AppliedPVar n > ttpCh t@(D u vs) (TNode c ps) = do > info <- getInfoE > case lookup u (dataDecls info) of > Nothing -> moanE $ TMissing u > Just (i, cs) -> > case lookup c cs of > Nothing -> moanE $ NoConstructor t c > Just ws -> (|(id *** PC c) (ttpsCh c (xsub vs ws) ps)|) > ttpCh v (TNode c _) = moanE $ NoConstructor v c > ttpsCh :: Template -> [VT] -> [TTree Pat] -> ElabM (Bwd Entry, [PAT]) > ttpsCh f [] [] = (| ~B0, ~[] |) > ttpsCh f (v : vs) (t : ts) = do > v <- hnf v > (| disjoinC (ttpCh v t) (ttpsCh f vs ts) @ |) > ttpsCh f _ _ = moanE $ PatArityError f > disjoin :: Bwd Entry -> Bwd Entry -> ElabM (Bwd Entry) > disjoin ez fz = (|(mappend ez fz) (-traverse chk fz-)|) where > chk e@(x ::: _) = traverse (occ x) ez > chk e = (|B0|) > occ x (y ::: _) | x == y = moanE $ RepeatedPVar x > occ x _ = (|()|) > disjoinC :: (Bwd Entry, PAT) -> (Bwd Entry, [PAT]) -> > ElabM (Bwd Entry, [PAT]) > disjoinC (ez, p) (fz, ps) = (|disjoin ez fz, ~(p : ps)|) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% Patterns for Template Resolution %%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > patTree :: [Pat] -> [TTree Pat] -> ElabM (TTree Pat) > patTree ps ts = do > tbl <- (|templateT getInfoE|) > case pa (resolve tbl) (map (patPunc tbl) ps) of > [(t, [])] -> case t of > TLeaf (PA ps) ts -> patTree ps ts > t -> return (tApp t ts) > _ -> moanE $ AmbiguousPats ps > where > patPunc tbl (PN x) | punc tbl x = Left x > patPunc tbl p = Right p