packages feed

LambdaPrettyQuote-0.0.0.6: src/Language/Lambda/Quote.hs

{-# LANGUAGE TemplateHaskell, QuasiQuotes, RankNTypes #-}
module Language.Lambda.Quote (lam, g_lam) where
import Language.Haskell.TH.Quote
import Language.Haskell.TH
import Language.Lambda.Parser
import Text.Parsec (runParser)
import Data.Generics.Aliases
import Data.Generics.Uniplate.Data
import Language.Lambda.AST
import Data.Data
import Debug.Trace.Helpers
 
lam :: QuasiQuoter
lam = g_lam parse_sym

g_lam :: (Data s, Show s) => SymParser () s -> QuasiQuoter
g_lam sp = QuasiQuoter (g_quoteExprExp sp) (g_quoteExprPat sp) undefined undefined


parseExpr :: Monad m => SymParser () s -> (String, Int, Int) -> String -> m (Output s)
parseExpr sp (file, line, col) s = result where
    result = case runParser (top_expr sp) () file s of
                  Left err  -> fail $ (show err ++ " at file " ++ file ++ " at line " ++ 
                                          show line ++ " at col " ++ show col)
                  Right e   -> return e
    

    
g_quoteExprExp :: (Data s, Show s,  Typeable s) => SymParser () s -> String -> ExpQ
g_quoteExprExp sp r =  do  
    loc <- location
    let pos =  (loc_filename loc,
             fst (loc_start loc),
             snd (loc_start loc))
    parsed_expr <- (parseExpr sp) pos r
    appE (varE $ mkName "meta_to_expr") $ dataToExpQ (const Nothing `extQ` 
        (antiExprExp sp)) $ parsed_expr
             
antiExprExp :: (Data s, Typeable s) => SymParser () s -> MetaExpr s -> Maybe (Q Exp)
antiExprExp d (MLam (AntiSym v) x) = Just $ appE (appE (conE $ mkName "MLam") $ appE (conE $ mkName "S") $ varE (mkName v))
                                         $ dataToExpQ (const Nothing `extQ` (antiExprExp d)) x
antiExprExp d (MVar (AntiSym v))   = Just $ appE (conE $ mkName "MVar") $ appE (conE $ mkName "S") $ varE (mkName v)
antiExprExp d (AntiExpr v)         = Just $ appE (varE $ mkName "to_meta") $ varE (mkName v)
antiExprExp d (AntiVar v)          = Just $ [| MVar (S $(varE $ mkName v)) |]
antiExprExp _ _                    = Nothing

g_quoteExprPat :: (Data s, Show s, Typeable s) => SymParser () s ->  String -> PatQ
g_quoteExprPat sp r =  do  
    loc <- location
    let pos =  (loc_filename loc,
             fst (loc_start loc),
             snd (loc_start loc))
    parsed_expr <- (parseExpr sp) pos r
    th_pat <- dataToPatQ (const Nothing `extQ` (antiExprPat sp)) parsed_expr
    return $ to_e th_pat where
        to_e p = transform to_e' p

        to_e' (ConP n xs) | show n == "MVar" = ConP (to_expr_name n) [collapse_meta_sym $ head xs]
        to_e' (ConP n xs) | show n == "MLam" = ConP (to_expr_name n) ((collapse_meta_sym $ head xs):(tail xs))
        to_e' (ConP n xs) | otherwise        = ConP (to_expr_name n) xs
        to_e' x = x

        to_expr_name name | show name == "MVar" = mkName "Var" 
        to_expr_name name | show name == "MApp" = mkName "App" 
        to_expr_name name | show name == "MLam" = mkName "Lam"
        to_expr_name name | otherwise           = name
        
        collapse_meta_sym (ConP n xs) | nameBase n == "S" = head xs
        collapse_meta_sym p@(ConP n xs) | otherwise = error ("collapse_meta_sym not used on a S " ++ show p)
             
antiExprPat :: (Data s, Typeable s) => SymParser () s -> MetaExpr s -> Maybe (Q Pat)
antiExprPat d (MLam (AntiSym v) x) = Just $ conP (mkName "MLam") [conP (mkName "S") [varP (mkName v)], 
                                        dataToPatQ (const Nothing `extQ` (antiExprPat d)) x]
antiExprPat d (MVar (AntiSym v))   = Just $ conP (mkName "MVar") [conP (mkName "S") [varP (mkName v)]]
antiExprPat d (AntiExpr v)         = Just $ varP (mkName v)
antiExprPat d (AntiVar v)          = Just $ conP (mkName "MVar") [conP (mkName "S") [varP $ mkName v]]
antiExprPat _ _                    = Nothing