{-# LANGUAGE OverloadedStrings, LambdaCase #-} -- | -- This module implements HGMPification of funcons based on Berger et al. (2017) -- (First-order.) module Funcons.MetaProgramming where import Funcons.MSOS import Funcons.EDSL import Funcons.Types import Funcons.Patterns import Funcons.RunOptions import Funcons.Simulation import Data.Maybe (fromJust) import Data.Text (pack, unpack) import qualified Data.Map as M import qualified Data.Set as S -- | This function implements the ==CT=> relation. -- Compiling programs to executable funcons terms, -- removing occurrences of `meta-up`, `meta-down` and `meta-let` and `meta-bound`. ctRel :: Funcons -> MSOS Funcons ctRel f = case f of FName nm -> return f FApp "meta-up" [m] -> ulRel m FApp "meta-down" [m] -> staticEval m FApp "meta-let" [FValue nm,m,n] | isString_ nm -> do v <- evalRel =<< ctRel m [menv] <- getInh env_entity let env' = case menv of Map env -> Map (M.insert nm [v] env) _ -> Map (M.singleton nm [v]) withInh env_entity [env'] (ctRel n) FApp nm arg -> FApp nm <$> mapM ctRel arg -- FList fs -> FList <$> mapM ctRel fs FSet fs -> FSet <$> mapM ctRel fs FMap fs -> FMap <$> mapM ctRel fs FValue (ADTVal nm fs) -> FValue . ADTVal nm <$> mapM ctRel fs FValue (ComputationType (Type (ADT nm fs))) -> FValue . ComputationType . Type . ADT nm <$> mapM ctRel fs FValue v -> return (FValue v) _ -> liftRewrite (sortErr f ("ctRel not defined")) where staticEval m = ctRel m >>= evalRel >>= liftRewrite . dlRel -- | This function implements the ==UL=> relation. -- Translating a funcon into its meta-representation ulRel :: Funcons -> MSOS Funcons ulRel f = case f of FName nm -> return $ ast_term [string_ (unpack nm)] FApp "meta-down" [f] -> ctRel f FApp "meta-up" [m] -> ulRel m >>= ulRel FApp nm fs -> ast_term . (string_ (unpack nm):) <$> mapM ulRel fs -- FList fs -> ast_term . (string_ "list":) <$> mapM ulRel fs FSet fs -> ast_term . (string_ "set":) <$> mapM ulRel fs FMap fs -> ast_term . (string_ "map":) <$> mapM ulRel fs FValue v -> return $ ast_value [type_ (tyOf v), FValue v] -- What TODO with type annotations? _ -> liftRewrite (sortErr f ("ulRel not defined")) -- | This function implements the ==DL=> relation. -- Translating a meta-representation of a program into the actual program dlRel :: Values -> Rewrite Funcons dlRel v = case v of ADTVal "ast-value" [t,v] | Just (ComputationType _) <- project t -> return v ADTVal "ast-term" [nm] | isString nm -> return (FName (pack (unString (fromJust (project nm))))) ADTVal "ast-term" (s:vs') | Just vs <- mapM project vs' , isString s, "set" <- unString (fromJust (project s)) -> FSet <$> mapM dlRel vs ADTVal "ast-term" (m:vs') | Just vs <- mapM project vs' , isString m, "map" <- unString (fromJust (project m)) -> FMap <$> mapM dlRel vs ADTVal "ast-term" (nm:vs') | Just vs <- mapM project vs' , isString nm -> FApp (pack (unString (fromJust (project nm)))) <$> mapM dlRel vs _ -> sortErr (meta_down_ (fvalues [v])) "meta-down not applied to a meta-representation" evalRel :: Funcons -> MSOS Values evalRel f = evalFuncons f >>= \case Right [v] -> return v Right vs -> liftRewrite $ internal "meta evaluation yields a sequence of values" Left f' -> evalRel f' where setGlobal f ctxt = ctxt { ereader = (ereader ctxt) { global_fct = f } } compile :: FunconLibrary -> TypeRelation -> Funcons -> Funcons -> Funcons compile lib tyenv fenv f = case runSimIO (runMSOS process (cmp_MSOSReader lib tyenv f) cmp_MSOSState) M.empty of ((Left ie , _,_), _) -> error ("failed to compile\n" ++ showIException ie) ((Right f, _, _), _) -> f where process = do env <- evalRel fenv putMut atom_gen_entity (Set S.empty) putMut store_entity (Map M.empty) withInh env_entity [env] (ctRel f) env_entity = "environment" store_entity = "store" atom_gen_entity = "used-atom-set" translationStep :: ([Funcons] -> Funcons) -> StrictFuncon translationStep f vs = compstep $ do fs <- liftRewrite (mapM dlRel vs) Left <$> ulRel (f fs) cmp_MSOSReader lib env f = MSOSReader cmp_RewriteReader M.empty M.empty (fread True) where cmp_RewriteReader = RewriteReader lib env defaultRunOptions f f --cmp_MSOSWriter = MSOSWriter mempty mempty mempty cmp_MSOSState = MSOSState M.empty M.empty (RewriteState) library :: FunconLibrary library = libFromList [ -- ("meta-up", NonStrictFuncon step_meta_up) -- static funcon -- , ("meta-down", StrictFuncon step_meta_down) -- static funcon ("eval", StrictFuncon step_meta_eval) , ("code", NonStrictFuncon step_code) , ("type-of", StrictFuncon step_ty_of) ] meta_up_ = applyFuncon "meta-up" meta_down_ = applyFuncon "meta-down" meta_let_ = applyFuncon "meta-let" eval_ = applyFuncon "eval" code_ = applyFuncon "code" step_meta_eval :: [Values] -> Rewrite Rewritten step_meta_eval [v] = dlRel v >>= rewriteTo step_meta_eval fs = sortErr (eval_ (fvalues fs)) "eval not applied to one argument" step_code :: [Funcons] -> Rewrite Rewritten step_code [f] = compstep (toStepRes <$> ulRel f) step_code fs = sortErr (code_ fs) "code not applied to a single term" ast_term = applyFuncon "ast-term" ast_value = applyFuncon "ast-value" type_of_ = applyFuncon "type-of" step_ty_of :: [Values] -> Rewrite Rewritten step_ty_of [v] = rewriteTo $ type_ $ tyOf v step_ty_of vs = sortErr (type_of_ (fvalues vs)) "type-of not applied to a single value" --TODO perhaps the parser should be extended to recognise "ast-" prefixes -- which are translated into applications of VMeta