packages feed

Hs2lib-0.5.7: Tests/Exec/Analyze.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Windll
-- Copyright   :  (c) Tamar Christina 2009 - 2010
-- License     :  BSD3
-- 
-- Maintainer  :  tamar@zhox.com
-- Stability   :  experimental
-- Portability :  portable
--
-- This module contains code to analyze datatypes in order to generate
-- QuickCheck arbitrary instances.
--
-----------------------------------------------------------------------------

module Tests.Exec.Analyze where

import WinDll.Identifier
import WinDll.Utils.Feedback
import WinDll.Session.Hs2lib
import WinDll.Structs.Structures

import Data.Monoid

import Tests.Exec.Structs

-- | Measure the costs of the datatypes of modules and 
--   create the generator functions for these types.
analyzeModule :: Exec [Arbitrary]
analyzeModule 
  = do modinfo <- generateMain
       let (normal, special) = modDatatypes modinfo
           values            = normal `mappend` special
       datatypes <- mapM (measureCost values) values
       
       mapM (liftIO . print) datatypes
       
       return datatypes
       
-- | Measure the costs of the datatype's constructor 
--   so we know how to generate instances of the datatype
measureCost :: DataTypes -> DataType -> Exec Arbitrary
measureCost lst dtype 
  = do let atype x = Arbitrary { arName  = dtName dtype
                               , arVars  = dtVars dtype
                               , arCons  = x
                               , arCosts = (0,0)
                               , arTag   = dtTag dtype
                               }
           consts  = getConstructors dtype
       
       arbs <- mapM (getConCost lst) consts
       
       let costs = getTypeCosts arbs
       
       return $ (atype arbs){arCosts = costs}
                               
-- | Get the minimum and maximum costs of a type by looking at the
--   costs of the constructors of the type.
getTypeCosts :: Arbitraries -> (Int, Int) 
getTypeCosts [] = (0,0)
getTypeCosts ((v@Variant{}):xs) = let cost               = arCost v
                                      (minCost, maxCost) = getTypeCosts xs
                                  in (minCost `min` cost, maxCost `max` cost)
getTypeCosts _  = (0,0)
                               
-- | returns the constructors of a type
getConstructors :: DataType -> DataTypes
getConstructors (DataType _ _ x _) = x
getConstructors (NewType  _ _ x _) = [x]
getConstructors (x@Constr{})       = [x]

-- | Get the cost of the constructors.
getConCost :: DataTypes -> DataType -> Exec Arbitrary
getConCost lst (Constr n f ann) 
   = do let var = Variant { arCost  = 0
                          , arName  = n
                          , arFix   = f
                          , arNamed = []
                          }
        return var
getConCost _ _ = die "getConCost can only determine the cost of constructors. try 'measureCost' instead"