packages feed

CSPM-Frontend-0.2.10.2: src/Language/CSPM/ReorderBindings.hs

{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Language.CSPM.ReorderBindings
-- Copyright   :  (c) Fontaine 2008
-- License     :  BSD
-- 
-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
-- Stability   :  experimental
-- Portability :  GHC-only
--
-- Rule out multiple recursive bindinggroups.
-- Reorder bindings for a call by value strategy.
-- ToDo: think if this is correct.
-- to be safe, we must also rule out multiple recursive functions ?
-- ToDo: add support for channel delcs and other top-level decls

module Language.CSPM.ReorderBindings
  (
  reorderModule
  )
where

import Language.CSPM.AST hiding (prologMode)
import qualified Language.CSPM.AST as AST
import qualified Language.CSPM.SrcLoc as SrcLoc

import Data.Data
import Data.Generics.Schemes (everything,everywhereM)
import Data.Generics.Aliases (mkM,extQ,mkQ)
import Data.Generics.Basics (gmapQ,toConstr,showConstr)
import Control.Exception (Exception)
import Data.Set (Set)
import qualified Data.Set as Set
import Control.Monad.Error

data BindError
  = BindError
  {
   bindErrorMsg :: String
  ,bindErrorLoc :: SrcLoc.SrcLoc
  } deriving (Show,Typeable)

instance Exception BindError
instance Error BindError where
  noMsg    = BindError "unknown" SrcLoc.NoLocation
  strMsg x = BindError x SrcLoc.NoLocation

type RM x = Either BindError x

-- | reorderModule expects an AST that has gone through renaming
reorderModule :: LModule -> RM LModule
reorderModule ast = do
  a2 <- everywhereM (mkM fixLet) ast
  reorderTopLevel a2
  where
    fixLet :: LExp -> RM LExp
    fixLet node = case unLabel node of
       Let decls e -> do
          d <- reorderGroup decls
          return $ setNode node $ Let d e
       _ -> return node
         
    reorderTopLevel :: LModule -> RM LModule
    reorderTopLevel = error "reorder Toplevel"

reorderGroup :: [LDecl] -> RM [LDecl]
reorderGroup l = do
  let d = map (\x -> (x, defs x, uses x)) l
  return $ error "reorderGroup"

-- | Compute the set of Identifier that get defined 
-- | Todo: unit-tests for this
defs :: LDecl -> Set UniqueIdent
defs d = case unLabel d of
  PatBind lpat _ -> everything Set.union ( Set.empty `mkQ` fromPattern) lpat
  FunBind i _ -> Set.singleton $ unUIdent $ unLabel i
  _ -> Set.empty  -- todo : add missing cases for top-level decls
  where
    fromPattern :: Pattern -> Set UniqueIdent
    fromPattern (VarPat i) = Set.singleton $ unUIdent $ unLabel i
    fromPattern _ = Set.empty

-- | Uses is NOT the free names analysis.
-- | We omit everything inside prefix-operations. (ToDO)
-- | Todo: think if this is correkt
uses :: LDecl -> Set UniqueIdent
uses d = case unLabel d of
  PatBind _ e -> collectVars e
  FunBind _ cases -> collectVars cases
  _ -> Set.empty  -- todo : add missing cases for top-level decls
  where
    collectVars :: Data t => t -> Set UniqueIdent
    collectVars = everything Set.union ( Set.empty `mkQ` fromExpr)
-- | We omit everything inside prefix-operations. (ToDO)
    fromExpr :: Exp -> Set UniqueIdent
    fromExpr (Var i) = Set.singleton $ unUIdent $ unLabel i
    fromExpr _ = Set.empty