packages feed

hfusion-0.0.6.1: HFusion/Internal/Parsing/HyloContext.lhs

-- Please, see the file LICENSE for copyright and license information.

> module HFusion.Internal.Parsing.HyloContext(
>           Context
>          ,emptyContext           -- :: Context
>          ,extractContext         -- :: [Def] -> [(Context,Def)]
>          ,mergeContext           -- :: [(Context,Def)] -> [Def]
>          ,findConstantArguments  -- :: [Def] -> [Int]
>          ,getConstantArgs        -- :: Context -> [Variable]
>          ,getCntArgPos           -- :: Context -> Maybe [Int]
>          ,combineContexts        -- :: Context -> Context -> Context
>        ) where
> import HFusion.Internal.HsPretty()
> import HFusion.Internal.HsSyn
> import HFusion.Internal.Utils
> import Data.List(intersect,(\\),delete)

A context contains the names of the constant arguments and the positions at which they appear.

> data Context = Ctx [Variable] (Maybe [Int])
>  deriving Show

> emptyContext :: Context
> emptyContext = Ctx [] Nothing

> getConstantArgs :: Context -> [Variable]
> getConstantArgs (Ctx vrs _) = vrs

> getCntArgPos :: Context -> Maybe [Int]
> getCntArgPos (Ctx _ pos) = pos

> combineContexts :: Context -> Context -> Context
> combineContexts (Ctx vs _) (Ctx vs' _) = Ctx (vs++vs') Nothing

> instance Vars Context where
>  vars (Ctx vs _) = vs

> instance AlphaConvertible Context where
>   alphaConvert sc ss (Ctx vrs pos) = Ctx (map (alphaConvert sc ss) vrs) pos

> extractContext :: [Def] -> [(Context,Def)]
> extractContext dfs@(firstd:taild) = (ctx,removeArgsDef firstd) 
>                                   : map (\d -> (ctx,sustDef (zip (getVars d) vrs)$ removeArgsDef d)) taild
>   where idxs = findConstantArguments dfs
>         vrs = getVars firstd
>         ctx = Ctx vrs (Just idxs)
>         getVars :: Def -> [Variable]
>         getVars (Defvalue _ t) = [ v | (i,Bvar v)<-zip [0..] (fst$ extractVars t), elem i idxs ]
>         removeArgsDef (Defvalue v t) = Defvalue v (removeArgs (map getDefName dfs) idxs t)
>         sustDef ss (Defvalue v t) = Defvalue v (substitution ss' t)
>            where ss' = map (\(v,v')->(v,Tvar v'))$ filter (\(v,v')->v/=v')$ ss
> extractContext []  = [] 

> mergeContext :: [(Context,Def)] -> [Def]
> mergeContext dfs = map (merge (map (getDefName.snd) dfs)) dfs 
>   where merge fs (Ctx vs idxs,Defvalue v t) = Defvalue v (addArgs fs (zip vs$ maybe [0..] id idxs) t)

removeArgs rmvs f t 
Removes arguments from a given recursive definition f = t. 
rmvs is the list of indexes of arguments to remove from each mutually recursive definition

> removeArgs :: [Variable] -> [Int] -> Term -> Term
> removeArgs fs idxs t = foldr Tlamb (rmFromCalls (fs\\vars vsis) t') (removeFromList vsis idxs)
>   where (vsis,t') = extractVars t
>         rmFromCalls = transformTerm . removeFromCalls
>         removeFromCalls fs (Tfapp v ts) tr | elem v fs = Tfapp v (removeFromList ts idxs)
>                                              | otherwise = tr
>         removeFromCalls fs (Tcase t0 ps ts) _ = Tcase (rmFromCalls fs t0) ps 
>                                                       (zipWith (rmFromCalls . (fs\\) . vars) ps ts)
>         removeFromCalls fs (Tlet v t0 t1) _ = Tlet v (rmFromCalls (delete v fs) t0) (rmFromCalls (delete v fs) t1)
>         removeFromCalls fs (Tlamb bv t) _ = Tlamb bv (rmFromCalls (fs\\vars bv) t)
>         removeFromCalls _ _ tr = tr
>         removeFromList xs idxs = [ x | (i,x)<-zip [0..] xs,notElem i idxs]

Adds some variables at the beginning of recursive calls and definitions.
addArgs [r] [v1,v2] (\v -> ... r vk ...)
yields
\v1 v2 v -> r v1 v2 vk

> addArgs :: [Variable] -> [(Variable,Int)] -> Term -> Term
> addArgs fs vs t = foldr Tlamb (addArgCalls fs t') (insertElems (map (applyFst Bvar) vs) vsis)
>   where (vsis,t') = extractVars t
>         tvs = map (applyFst Tvar) vs
>         addArgCalls = transformTerm . addToCalls
>         addToCalls fs (Tfapp v ts) tr | elem v fs = Tfapp v (insertElems tvs ts)
>                                         | otherwise = tr
>         addToCalls fs (Tcase t0 ps ts) _ = Tcase (addArgCalls fs t0) ps 
>                                                   (zipWith (addArgCalls . (fs\\) . vars) ps ts)
>         addToCalls fs (Tlet v t0 t1) _ = Tlet v (addArgCalls (delete v fs) t0) (addArgCalls (delete v fs) t1)
>         addToCalls fs (Tlamb bv t) _ = Tlamb bv (addArgCalls (fs\\vars bv) t)
>         addToCalls _ _ tr = tr


returns the indexes of the constant arguments of a set of mutually recursive definitions.

> findConstantArguments :: [Def] -> [Int]
> findConstantArguments dfs = foldr1 intersect  . map (findConstantArgs' (map getDefName dfs))$ dfs
>   where findConstantArgs' fs (Defvalue _ t) = getIndexes$ foldr (zipWith matchArg) (map maybeBvar vsis) (collectCalls (fs\\vars vsis) t')
>           where (vsis,t') = extractVars t
>         collectCalls :: [Variable] -> Term -> [[Maybe Variable]]
>         collectCalls fn t =
>            case t of
>              Tvar _ -> []
>              Tlit _ -> []
>              Tbottom -> []
>              Ttuple _ ts -> concatMap (fcaa fn) ts
>              Tcase t0 ps ts -> fcaa fn t0 ++ concat (zipWith (\p->except p . fcaa (fn\\vars p)) ps ts)
>              Tcapp _ ts -> concatMap (fcaa fn) ts
>              Tapp t0 t1 -> fcaa fn t0 ++ fcaa fn t1
>              Tlet v t0 t1 -> except v (fcaa (delete v fn) t0 ++ fcaa (delete v fn) t1)
>              Tlamb bv t -> except bv$ fcaa (fn\\vars bv) t
>              Tfapp v ts -> if elem v fn && null (intersect fn (vars ts))
>                              then [map maybeTvar ts]
>                              else concatMap (fcaa fn) ts
>              _ -> error ("findConstantArgs: non-expected term: "++show t)
>           where fcaa fn = collectCalls fn 
>         except :: Vars a => a -> [[Maybe Variable]] -> [[Maybe Variable]]
>         except t = map (map except')
>           where tvs = vars t
>                 except' (Just v) | elem v tvs = Nothing
>                 except' mv = mv
>         maybeTvar (Tvar v) = Just v
>         maybeTvar _ = Nothing
>         maybeBvar (Bvar v) = Just v
>         maybeBvar _ = Nothing
>         matchArg (Just v) (Just v') | v==v' = Just v
>         matchArg _ _ = Nothing
>         getIndexes ls = [ i | (i,Just _)<-zip [0..] ls ]