packages feed

curry-base 0.2.3 → 0.2.4

raw patch · 7 files changed

+374/−7 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Curry.ExtendedFlat.LiftLetrec: liftLetrecProg :: Prog -> Prog
+ Curry.ExtendedFlat.UnMutual: unMutualProg :: Prog -> Prog

Files

Curry/Base/MessageMonad.hs view
@@ -1,9 +1,12 @@ {-# LANGUAGE FlexibleContexts #-} {--  The \texttt{MsgMonad} type is used for describing the result of a-  computation that can fail. In contrast to the standard \texttt{Maybe}-  type, its \texttt{Error} case provides for an error message that-  describes the failure.+  The monads MsgMonad and MsgMonadIO provide a common way+  to log warning messages and to stop execution when an+  error occurs. They may be used to integrate different+  compiler passes smoothly.++  (c) 2009, Holger Siegel.+ -}  module Curry.Base.MessageMonad where
+ Curry/ExtendedFlat/LiftLetrec.hs view
@@ -0,0 +1,98 @@+{-+  Turn recursive data declarations into recursive+  function calls.++  Only single recursive declarations are transformed.+  Mutually recursive declarations are left unchanged.+  You should use transformation UnMutual first.++  (c) 2009, Holger Siegel.+-}++module Curry.ExtendedFlat.LiftLetrec(liftLetrecProg) where++import Data.List+import Control.Monad.State+import Data.Maybe+import qualified Data.Map as Map+import qualified Data.Set as Set++import Curry.ExtendedFlat.Type+import Curry.ExtendedFlat.Goodies+import Curry.ExtendedFlat.MonadicGoodies++++data LifterState = LifterState { modname :: String,+                                 currentFunc :: String,+                                 globals :: Set.Set QName,+                                 globalCounter :: Map.Map QName Int,+                                 localCounter :: Int,+                                 lifted :: Map.Map QName FuncDecl }+++type Bind = (VarIndex, Expr)    -- (name, value)+type LiftMonad = State LifterState+++liftLetrecProg :: Prog -> Prog+liftLetrecProg prog = updProg id id id (++ fdecls) id prog'+    where state = LifterState {+                    modname = progName prog,+                    currentFunc = "anonymous",+                    globals = Set.fromList g,+                    globalCounter = Map.fromList $ zip g (repeat 1),+                    localCounter = 0,+                    lifted = Map.empty+                  }+          g = allGlobals prog+          (prog', state') = runState (updProgFuncsM run prog) state+          fdecls = Map.elems (lifted state')+          run fdecl = do+            let fname = localName (funcName fdecl)+            modify (\st -> st { currentFunc  = fname,+                                localCounter = (maximum . map idxOf . allVarsInFunc) fdecl+                              })+            fdecl' <- updFuncLetsM liftRecursion fdecl+            modify (\st -> st {currentFunc = "anonymous"})+            return fdecl'++++liftRecursion :: [Bind] -> Expr -> LiftMonad Expr+liftRecursion [(b, rhs)] body+    | b `elem` fv = do globalcall <- mkLiftedFunction (typeofVar b) b rhs (fv \\ [b])+                       return (Let [(b, globalcall)] body)+    | otherwise  = return (Let [(b, rhs)] body)+    where fv = fvs rhs+liftRecursion bs body = return (Let bs body)+++mkLiftedFunction :: Maybe TypeExpr -> VarIndex -> Expr -> [VarIndex] -> LiftMonad Expr+mkLiftedFunction t v rhs fv +    = do name <- newGlobalName t+         st <- get+         let fcall = (Comb FuncCall name (map Var fv))+         -- FIXME Typ der Funktion muss irgendwie ermittelt werden :(+         let fdecl = Func name (length fv) Private (fromMaybe (TVar 0) t) (Rule fv (Let [(v,fcall)] rhs))+         put st { lifted = Map.insert name fdecl (lifted st),+                  globals = Set.insert name (globals st)+                }+         return fcall+++newGlobalName :: Maybe TypeExpr -> LiftMonad QName+newGlobalName t+    = do st <- get+         let qn = QName Nothing t (modname st) (currentFunc st)+         let counter = Map.findWithDefault 1 qn (globalCounter st)+         put st { globalCounter = Map.insert qn (counter + 1) (globalCounter st) }+         let qn' = QName Nothing t (modname st) (localName qn ++ "_" ++ show counter)+         if qn' `Set.member` globals st+             then newGlobalName t+             else return qn'+++allGlobals :: Prog -> [QName]+allGlobals prog = [n | Func n _ _ _ _ <- fs]+    where fs = progFuncs prog
Curry/ExtendedFlat/MonadicGoodies.hs view
@@ -1,3 +1,9 @@+{-+  Monadic transformations of ExtendedFlat programs.++  (c) 2009, Holger Siegel.+-}+ module Curry.ExtendedFlat.MonadicGoodies     (UpdateM, postOrderM,      updFuncExpsM, updProgFuncsM, updFuncLetsM) where
Curry/ExtendedFlat/TypeInference.hs view
@@ -1,5 +1,16 @@ {-# LANGUAGE FlexibleContexts, PatternGuards #-} +{-+  Function adjustTypeInfos annotates every declaration,+  identifier, and application with exact type information.++  This information is derived from the more general information+  found in the AST.++  (c) 2009, Holger Siegel.++-}+ module Curry.ExtendedFlat.TypeInference     ( dispType,       adjustTypeInfo,
+ Curry/ExtendedFlat/UnMutual.hs view
@@ -0,0 +1,238 @@+{-# LANGUAGE RecursiveDo #-}++{-+  Turns mutually recursive declarations into a single recursive+  declaration, of a tuple value, trying to minimize the number+  of the tuple. This is an implementation of the algorithm described in+  http://www.informatik.uni-kiel.de/~mh/lehre/diplomarbeiten/siegel.pdf++  (c) 2009, Holger Siegel.+-}+module Curry.ExtendedFlat.UnMutual(unMutualProg) where++import Data.Graph+-- import Data.Function(on)+import Data.Maybe+import Data.List+import Control.Monad.State++import Curry.Base.Position(noRef)+import Curry.ExtendedFlat.Type+import Curry.ExtendedFlat.Goodies+import Curry.ExtendedFlat.MonadicGoodies+++type Bind = (VarIndex, Expr)    -- (name, value)++newtype UnMutualState = UnMutualState { localCounter :: Int }+++type UnMutualMonad = State UnMutualState+++unMutualProg :: Prog -> Prog+unMutualProg p = evalState (updProgFuncsM +                            (\fdecl -> do +                               modify (\st -> st { localCounter = (maximum . map idxOf . allVarsInFunc) fdecl})+                               updFuncLetsM rmMutualRecursion fdecl)+                            p) (UnMutualState 1000)++rmMutualRecursion :: [Bind] -> Expr -> UnMutualMonad Expr+rmMutualRecursion bs body+    | allWhnf bs || length bs <= 1+        = return (Let bs body)+    | otherwise+        = mdo (body', bound, fbs) <- partitionBinds (fvs body) sccs (body, mkTuple fbs, [])+              mkSingleLet body' bound fbs+    where fvsGraph    = depGraph bs+          sccs        = sortSccs fvsGraph+++mkSingleLet :: Expr -> Expr -> [VarIndex] -> UnMutualMonad Expr+mkSingleLet e2 e1 [v]+      = return (Let [(v, e1)] e2)+mkSingleLet body bound fbs+    = do recname <- newLocalName (Just fbsType)+         bound' <- mkFbSelectors recname bound+         body' <- mkFbSelectors recname body++         return (Let [(recname, bound')] body')+    where+      fbsType = TCons (mkQName tuplecon) (map (fromJust . typeofVar) fbs)+      tuplecon =  ("Prelude", "(" ++ replicate (length fbs -1 ) ',' ++ ")")+      mkFbSelectors recname b  = foldM (mkSelector recname)b fbs+      mkSelector recname b v   = nonrecLet v (mkSel (Var recname) v fbs) b+++-- Some self-explaining helper functions:+++-- FIXME rename, wenn x in (fvs e1) !+-- immer rename wg. Shadowing+-- (siehe Test.curry)+nonrecLet :: VarIndex -> Expr -> Expr -> UnMutualMonad Expr+nonrecLet x e1 e2+    | x `elem` allVars e1 +        = do vi <- newLocalName (typeofVar x)+             let e2' = subst x (Var vi) e2+             return (Let [(vi,e1)] e2')+    | otherwise = return (Let [(x,e1)] e2)+++mkTuple :: [VarIndex] -> Expr+mkTuple [e]  = Var e+mkTuple es   = Comb ConsCall (mkTupleConstr es) $ map Var es+++mkTupleConstr :: [a] -> QName+mkTupleConstr arity = curry mkQName "Prelude" ("(" ++ replicate (length arity-1) ',' ++ ")")++mkSel :: Expr -> VarIndex -> [VarIndex] -> Expr+mkSel e v vs = Case noRef Rigid e  [Branch pat (Var v)]+    where  pat   = Pattern tcon vs+           tcon  = mkTupleConstr vs+++allWhnf :: [Bind] -> Bool+allWhnf = all (whnf . snd)++{-+The type |FvsNode| stands for a single node in a dependency graph.+It contains the binding, i.e. the identifier and the right hand side, as well+as a list of the identifiers the right hand side refers to.++Function |depGraph| turns a list of bindings into a dependency graph.++Function |sortSccs| calculates a list of strongly connected components+with the help of the library function |stronglyConnCompR|.+In contrast to the list of SCCs returned from this function,+the list of SCCs returned by |sortSccs| is in reversed order.+This is required, beacuase we start to process nested+declarations at the innermost binding.+-}++type FvsNode = (Bind, VarIndex, [VarIndex])++depGraph :: [Bind] -> [FvsNode]+depGraph = map (\(x, e) -> ((x, e), x, fvs e))+++sortSccs :: [FvsNode] -> [SCC FvsNode]+sortSccs = reverse . stronglyConnCompR+++{-+Function |partitionBinds| takes the following arguments: A list of identifier that occur+in the body of the declaration, a sorted list of strongy connected components,+a 3-tuple consising of the body of the declaration, a tuple expression that contains the+feedback variables, and the list of identifiers that are already added to the feedback set.+It returns an updated version of that 3-tuple, in which the body expression is 'surrounded'+by declarations of identifiers that the body refers to, the tuple expression is 'surrounded'+by declarations that are needed to define the feedback vriables, and the set of feedback+identifiers is the complete feedback set:+-}+partitionBinds :: [VarIndex] -> [SCC FvsNode] +               -> (Expr, Expr, [VarIndex])+               -> UnMutualMonad (Expr, Expr, [VarIndex])++-- When there is no binding left in a strongly connected component,+-- then move to the next SCC:+partitionBinds pull  (CyclicSCC []:ds) part+    = partitionBinds pull ds part++{- If the next SCC is cyclic, then pick the best candidate for the feedback set+and remove it from the SCC. The rest of the SCC breaks into smaller SCCs that are sorted+and added to the remaining list of SCCs. The selected candidate is added to the feedback set,+and its declaration is added to the tuple expression: -}+partitionBinds pull (CyclicSCC d:ds) (body, bound, fbs)+    = let (b@(v,e), d')  = pickFbNode pull d+          sccs      = sortSccs d' ++ ds+      in do l <- nonrecLet v e bound+            partitionBinds pull sccs (body, l, fst b:fbs)++-- If the next SCC is acyclic, then it is not added to the feedback set. Instead,+-- its declaration is added to the tuple expression. Depending on whether it+-- is needed in the body expression, its declaration is also  added to the body expression:+partitionBinds pull  (AcyclicSCC ((x,e),_,r):ds) (body, bound, fbs)+    = do l <- nonrecLet x e bound+         (body', pull') <- if x `elem` pull+                           then do l' <- nonrecLet x e body+                                   return (l', r `union` pull)+                           else return (body, pull)+         partitionBinds pull' ds (body', l, fbs)++-- When there are no more declarations to be processed, the 3-tuple is returned as+-- result:+partitionBinds _pull [] part+    = return part++++-- Function |pickFbNode| picks the best candidate from a SCC. Irs choice depends+-- not only on the SCC, but also on whether the candidate is referred to by the body expression:++pickFbNode :: [VarIndex] -> [FvsNode] -> (Bind, [FvsNode])+pickFbNode pull defs = (b, d)+    where +    ds         = [x | (_, x, _) <- defs]+    (b, y, _)  = maximumBy (compare `on` weight pull ds) defs+    d          = [ n | n@(_, x, _) <- defs, x /= y]++-- not in ghc 6.8.2:+on :: (b -> b -> c) -> (a -> b) -> a -> a -> c+on (.*.) f x y = f x .*. f y++{-+Function |weight| estimates the usefulness of adding an identifier to the feedback set.+It uses the fact, that tuples are sorted in exicographic order by default. An identifier is+rated on whether it+\begin{enumerate}+        \item has a recursive reference to itself,+        \item has a high number of references to other identifiers in the same SCC, or+        \item is referred to by the body expression.+\end{enumerate}+-}++weight :: [VarIndex] -> [VarIndex] -> FvsNode -> (Bool, Int, Bool)+weight pull defs (_,x,fv) = (recursive, length incoming, pulled)+    where  recursive  = x `elem` fv+           incoming   = fv `intersect` defs+           pulled     = x `elem` pull++++newLocalName :: Maybe TypeExpr -> UnMutualMonad VarIndex+newLocalName t+    = do st <- get+         let counter = 1 + localCounter st+         put st { localCounter = counter  }+         return (VarIndex t counter)+++subst :: VarIndex -> Expr -> Expr -> Expr+subst v x = po+    where po e@(Var v')+              | v==v'  = x+              | otherwise = e+          po e@(Lit _)+              = e+          po (Comb t n es)+              = Comb t n (map po es)+          po e@(Free vs e')+              | v `elem` vs = e+              | otherwise   = Free vs (po e')+          po e@(Let bs e') +              | lookup v bs == Nothing +              = Let (map poBind bs) (po e')+              | otherwise = e+          po (Or l r) = Or (po l) (po r)+          po (Case p t e bs) = Case p t (po e) (map poBranch bs)+          poBind  (w, rhs) = (w, po rhs)+          poBranch e@(Branch p rhs)+              | v `elem` trPattern (\_ args -> args) (const []) p+              = e+              | otherwise +              = Branch p (po rhs)+++
Curry/Files/Filenames.hs view
@@ -1,3 +1,13 @@+{-+  Filename mangling for several intermediate file formats.++  The functions in this module were collected from several+  compiler modules in order to provide a unique accessing+  point for this functionality.++  (c) 2009, Holger Siegel.+-}+ module Curry.Files.Filenames where  import System.FilePath
curry-base.cabal view
@@ -1,5 +1,5 @@ Name:          curry-base-Version:       0.2.3+Version:       0.2.4 Cabal-Version: >= 1.6 Synopsis:      Functions for manipulating Curry programs Description:   This package serves as a foundation for Curry compilers. it defines the intermediate@@ -17,8 +17,9 @@  Library   Build-Depends:    base >= 3 && < 4, mtl, old-time, directory, filepath, containers, pretty-  ghc-options:      -Wall -fwarn-unused-binds -fwarn-unused-imports  -auto-all+  ghc-options:         Exposed-Modules:  Curry.Base.Position, Curry.Base.Ident, Curry.Base.MessageMonad-                    Curry.ExtendedFlat.Type, Curry.ExtendedFlat.Goodies, Curry.ExtendedFlat.TypeInference, Curry.ExtendedFlat.MonadicGoodies+                    Curry.ExtendedFlat.Type, Curry.ExtendedFlat.Goodies, Curry.ExtendedFlat.TypeInference,+                    Curry.ExtendedFlat.MonadicGoodies, Curry.ExtendedFlat.UnMutual, Curry.ExtendedFlat.LiftLetrec                     Curry.FlatCurry.Type, Curry.FlatCurry.Goodies, Curry.FlatCurry.Tools                     Curry.Files.Filenames, Curry.Files.PathUtils