module GF.Grammar.Analyse (
        stripSourceGrammar,
        constantDepsTerm,
        sizeTerm,
        sizeConstant,
        sizesModule,
        sizesGrammar,
        printSizesGrammar
        ) where

import GF.Grammar.Grammar
import GF.Infra.Ident
import GF.Text.Pretty(render)
--import GF.Infra.Option ---
import GF.Grammar.Macros
import GF.Grammar.Lookup

import GF.Data.Operations

import qualified Data.Map as Map
import Data.List (nub)
--import Debug.Trace

stripSourceGrammar :: Grammar -> Grammar
stripSourceGrammar :: Grammar -> Grammar
stripSourceGrammar Grammar
sgr = [Module] -> Grammar
mGrammar [(ModuleName
i, ModuleInfo
m{jments :: Map Ident Info
jments = (Info -> Info) -> Map Ident Info -> Map Ident Info
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map Info -> Info
stripInfo (ModuleInfo -> Map Ident Info
jments ModuleInfo
m)}) | (ModuleName
i,ModuleInfo
m) <- Grammar -> [Module]
modules Grammar
sgr]

stripInfo :: Info -> Info
stripInfo :: Info -> Info
stripInfo Info
i = case Info
i of
  AbsCat Maybe (L Context)
_ -> Info
i
  AbsFun Maybe (L Type)
mt Maybe Int
mi Maybe [L Equation]
me Maybe Bool
mb -> Maybe (L Type)
-> Maybe Int -> Maybe [L Equation] -> Maybe Bool -> Info
AbsFun Maybe (L Type)
mt Maybe Int
mi Maybe [L Equation]
forall a. Maybe a
Nothing Maybe Bool
mb
  ResParam Maybe (L [Param])
mp Maybe [Type]
mt -> Maybe (L [Param]) -> Maybe [Type] -> Info
ResParam Maybe (L [Param])
mp Maybe [Type]
forall a. Maybe a
Nothing
  ResValue L Type
lt -> Info
i ----
  ResOper Maybe (L Type)
mt Maybe (L Type)
md -> Maybe (L Type) -> Maybe (L Type) -> Info
ResOper Maybe (L Type)
mt Maybe (L Type)
forall a. Maybe a
Nothing
  ResOverload [ModuleName]
is [(L Type, L Type)]
fs -> [ModuleName] -> [(L Type, L Type)] -> Info
ResOverload [ModuleName]
is [(L Type
lty, Location -> Type -> L Type
forall a. Location -> a -> L a
L Location
loc (Int -> Type
EInt Int
0)) | (L Type
lty,L Location
loc Type
_) <- [(L Type, L Type)]
fs]
  CncCat Maybe (L Type)
mty Maybe (L Type)
mte Maybe (L Type)
_ Maybe (L Type)
mtf Maybe PMCFG
mpmcfg -> Maybe (L Type)
-> Maybe (L Type)
-> Maybe (L Type)
-> Maybe (L Type)
-> Maybe PMCFG
-> Info
CncCat Maybe (L Type)
mty Maybe (L Type)
forall a. Maybe a
Nothing Maybe (L Type)
forall a. Maybe a
Nothing Maybe (L Type)
forall a. Maybe a
Nothing Maybe PMCFG
forall a. Maybe a
Nothing
  CncFun Maybe (Ident, Context, Type)
mict Maybe (L Type)
mte Maybe (L Type)
mtf Maybe PMCFG
mpmcfg -> Maybe (Ident, Context, Type)
-> Maybe (L Type) -> Maybe (L Type) -> Maybe PMCFG -> Info
CncFun Maybe (Ident, Context, Type)
mict Maybe (L Type)
forall a. Maybe a
Nothing Maybe (L Type)
forall a. Maybe a
Nothing Maybe PMCFG
forall a. Maybe a
Nothing
  AnyInd Bool
b ModuleName
f -> Info
i

constantsInTerm :: Term -> [QIdent]
constantsInTerm :: Type -> [QIdent]
constantsInTerm = [QIdent] -> [QIdent]
forall a. Eq a => [a] -> [a]
nub ([QIdent] -> [QIdent]) -> (Type -> [QIdent]) -> Type -> [QIdent]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> [QIdent]
consts where
  consts :: Type -> [QIdent]
consts Type
t = case Type
t of
    Q QIdent
c  -> [QIdent
c]
    QC QIdent
c -> [QIdent
c]
    Type
_ -> (Type -> [QIdent]) -> Type -> [QIdent]
forall m. Monoid m => (Type -> m) -> Type -> m
collectOp Type -> [QIdent]
consts Type
t

constantDeps :: Grammar -> QIdent -> Err [QIdent]
constantDeps :: Grammar -> QIdent -> Err [QIdent]
constantDeps Grammar
sgr QIdent
f = [QIdent] -> Err [QIdent]
forall (m :: * -> *) a. Monad m => a -> m a
return ([QIdent] -> Err [QIdent]) -> [QIdent] -> Err [QIdent]
forall a b. (a -> b) -> a -> b
$ [QIdent] -> [QIdent]
forall a. Eq a => [a] -> [a]
nub ([QIdent] -> [QIdent]) -> [QIdent] -> [QIdent]
forall a b. (a -> b) -> a -> b
$ ([QIdent] -> [QIdent]) -> [QIdent] -> [QIdent]
forall a. Eq a => ([a] -> [a]) -> [a] -> [a]
iterFix [QIdent] -> [QIdent]
more [QIdent]
start where
  start :: [QIdent]
start = QIdent -> [QIdent]
constants QIdent
f
  more :: [QIdent] -> [QIdent]
more  = (QIdent -> [QIdent]) -> [QIdent] -> [QIdent]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap QIdent -> [QIdent]
constants
  constants :: QIdent -> [QIdent]
constants QIdent
c = (QIdent
c QIdent -> [QIdent] -> [QIdent]
forall a. a -> [a] -> [a]
:) ([QIdent] -> [QIdent]) -> [QIdent] -> [QIdent]
forall a b. (a -> b) -> a -> b
$ [QIdent] -> Err [QIdent] -> [QIdent]
forall a. a -> Err a -> a
fromErr [] (Err [QIdent] -> [QIdent]) -> Err [QIdent] -> [QIdent]
forall a b. (a -> b) -> a -> b
$ do
    [Type]
ts  <- Grammar -> QIdent -> Err [Type]
termsOfConstant Grammar
sgr QIdent
c
    [QIdent] -> Err [QIdent]
forall (m :: * -> *) a. Monad m => a -> m a
return ([QIdent] -> Err [QIdent]) -> [QIdent] -> Err [QIdent]
forall a b. (a -> b) -> a -> b
$ (Type -> [QIdent]) -> [Type] -> [QIdent]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Type -> [QIdent]
constantsInTerm [Type]
ts

getIdTerm :: Term -> Err QIdent
getIdTerm :: Type -> Err QIdent
getIdTerm Type
t = case Type
t of
  Q QIdent
i  -> QIdent -> Err QIdent
forall (m :: * -> *) a. Monad m => a -> m a
return QIdent
i
  QC QIdent
i -> QIdent -> Err QIdent
forall (m :: * -> *) a. Monad m => a -> m a
return QIdent
i
  P (Vr Ident
r) Label
l -> QIdent -> Err QIdent
forall (m :: * -> *) a. Monad m => a -> m a
return (Ident -> ModuleName
MN Ident
r,Label -> Ident
label2ident Label
l) --- needed if term is received from parser
  Type
_ -> String -> Err QIdent
forall a. String -> Err a
Bad (String
"expected qualified constant, not " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Type -> String
forall a. Show a => a -> String
show Type
t)

constantDepsTerm :: Grammar -> Term -> Err [Term]
constantDepsTerm :: Grammar -> Type -> Err [Type]
constantDepsTerm Grammar
sgr Type
t = do
  QIdent
i <- Type -> Err QIdent
getIdTerm Type
t
  [QIdent]
cs <- Grammar -> QIdent -> Err [QIdent]
constantDeps Grammar
sgr QIdent
i
  [Type] -> Err [Type]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Type] -> Err [Type]) -> [Type] -> Err [Type]
forall a b. (a -> b) -> a -> b
$ (QIdent -> Type) -> [QIdent] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map QIdent -> Type
Q [QIdent]
cs  --- losing distinction Q/QC

termsOfConstant :: Grammar -> QIdent -> Err [Term]
termsOfConstant :: Grammar -> QIdent -> Err [Type]
termsOfConstant Grammar
sgr QIdent
c = case Grammar -> QIdent -> Err [([Type], (Type, Type))]
forall (m :: * -> *).
ErrorMonad m =>
Grammar -> QIdent -> m [([Type], (Type, Type))]
lookupOverload Grammar
sgr QIdent
c of
  Ok [([Type], (Type, Type))]
tts -> [Type] -> Err [Type]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Type] -> Err [Type]) -> [Type] -> Err [Type]
forall a b. (a -> b) -> a -> b
$ [[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Type
ty,Type
tr] | ([Type]
_,(Type
ty,Type
tr)) <- [([Type], (Type, Type))]
tts]
  Err [([Type], (Type, Type))]
_ -> [Type] -> Err [Type]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Type] -> Err [Type]) -> [Type] -> Err [Type]
forall a b. (a -> b) -> a -> b
$
         [Type
ty | Ok Type
ty <- [Grammar -> QIdent -> Err Type
forall (m :: * -> *). ErrorMonad m => Grammar -> QIdent -> m Type
lookupResType Grammar
sgr QIdent
c]] [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++  -- type sig may be missing
         [Type
ty | Ok Type
ty <- [Grammar -> QIdent -> Err Type
forall (m :: * -> *). ErrorMonad m => Grammar -> QIdent -> m Type
lookupResDef Grammar
sgr QIdent
c]]

sizeConstant :: Grammar -> Term -> Int
sizeConstant :: Grammar -> Type -> Int
sizeConstant Grammar
sgr Type
t = (String -> Int) -> (Int -> Int) -> Err Int -> Int
forall b a. (String -> b) -> (a -> b) -> Err a -> b
err (Int -> String -> Int
forall a b. a -> b -> a
const Int
0) Int -> Int
forall a. a -> a
id (Err Int -> Int) -> Err Int -> Int
forall a b. (a -> b) -> a -> b
$ do
  QIdent
c  <- Type -> Err QIdent
getIdTerm Type
t
  ([Type] -> Int) -> Err [Type] -> Err Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> ([Type] -> [Int]) -> [Type] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Type -> Int) -> [Type] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Int
sizeTerm) (Err [Type] -> Err Int) -> Err [Type] -> Err Int
forall a b. (a -> b) -> a -> b
$ Grammar -> QIdent -> Err [Type]
termsOfConstant Grammar
sgr QIdent
c

-- the number of constructors in a term, ignoring position information and unnecessary types
-- ground terms count as 1, i.e. as "one work" each
sizeTerm :: Term -> Int
sizeTerm :: Type -> Int
sizeTerm Type
t = case Type
t of
  App Type
c Type
a      -> Type -> Int
sizeTerm Type
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a  -- app nodes don't count 
  Abs BindType
_ Ident
_ Type
b    -> Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
b
  Prod BindType
_ Ident
_ Type
a Type
b -> Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
b 
  S Type
c Type
a        -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a
  Table Type
a Type
c    -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
c
  ExtR Type
a Type
c     -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
c
  R [Assign]
r          -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a | (Label
_,(Maybe Type
_,Type
a)) <- [Assign]
r]  -- label counts as 1, type ignored
  RecType [Labelling]
r    -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a | (Label
_,Type
a)     <- [Labelling]
r]  -- label counts as 1
  P Type
t Label
i        -> Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
t
  T TInfo
_ [Case]
cc       -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm (Patt -> Type
patt2term Patt
p) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
v | (Patt
p,Type
v) <- [Case]
cc]
  V Type
ty [Type]
cc      -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
ty Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
v | Type
v <- [Type]
cc]
  Let (Ident
x,(Maybe Type
mt,Type
a)) Type
b -> Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> (Type -> Int) -> Maybe Type -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 Type -> Int
sizeTerm Maybe Type
mt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
b
  C Type
s1 Type
s2      -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
s1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
s2 
  Glue Type
s1 Type
s2   -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
s1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
s2 
  Alts Type
t [(Type, Type)]
aa    -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
t Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Type -> Int
sizeTerm Type
p Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
v | (Type
p,Type
v) <- [(Type, Type)]
aa]
  FV [Type]
ts        -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Type -> Int) -> [Type] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Int
sizeTerm [Type]
ts)
  Strs [Type]
tt      -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Type -> Int) -> [Type] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Int
sizeTerm [Type]
tt)
  Type
_            -> Int
1


-- the size of a judgement
sizeInfo :: Info -> Int
sizeInfo :: Info -> Int
sizeInfo Info
i = case Info
i of
  AbsCat (Just (L Location
_ Context
co)) -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
ty | (BindType
_,Ident
_,Type
ty) <- Context
co]
  AbsFun Maybe (L Type)
mt Maybe Int
mi Maybe [L Equation]
me Maybe Bool
mb -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Maybe (L Type) -> Int
msize Maybe (L Type)
mt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 
    [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [[Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Patt -> Int) -> [Patt] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Type -> Int
sizeTerm (Type -> Int) -> (Patt -> Type) -> Patt -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Patt -> Type
patt2term) [Patt]
ps) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
t | Just [L Equation]
es <- [Maybe [L Equation]
me], L Location
_ ([Patt]
ps,Type
t) <- [L Equation]
es]
  ResParam Maybe (L [Param])
mp Maybe [Type]
mt -> 
    Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
ty | (BindType
_,Ident
_,Type
ty) <- Context
co] | Just (L Location
_ [Param]
ps) <- [Maybe (L [Param])
mp], (Ident
_,Context
co) <- [Param]
ps]
  ResValue L Type
lt -> Int
0
  ResOper Maybe (L Type)
mt Maybe (L Type)
md -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Maybe (L Type) -> Int
msize Maybe (L Type)
mt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Maybe (L Type) -> Int
msize Maybe (L Type)
md
  ResOverload [ModuleName]
is [(L Type, L Type)]
fs -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Type -> Int
sizeTerm Type
ty Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Type -> Int
sizeTerm Type
tr | (L Location
_ Type
ty, L Location
_ Type
tr) <- [(L Type, L Type)]
fs]
  CncCat Maybe (L Type)
mty Maybe (L Type)
_ Maybe (L Type)
_ Maybe (L Type)
_ Maybe PMCFG
_ -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Maybe (L Type) -> Int
msize Maybe (L Type)
mty   -- ignoring lindef, linref and printname
  CncFun Maybe (Ident, Context, Type)
mict Maybe (L Type)
mte Maybe (L Type)
mtf Maybe PMCFG
_ -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Maybe (L Type) -> Int
msize Maybe (L Type)
mte  -- ignoring type and printname
  AnyInd Bool
b ModuleName
f -> -Int
1  -- just to ignore these in the size
  Info
_ -> Int
0
 where 
  msize :: Maybe (L Type) -> Int
msize Maybe (L Type)
mt = case Maybe (L Type)
mt of
    Just (L Location
_ Type
t) -> Type -> Int
sizeTerm Type
t
    Maybe (L Type)
_ -> Int
0
{-
-- the size of a module
sizeModule :: SourceModule -> Int
sizeModule = fst . sizesModule
-}
sizesModule :: SourceModule -> (Int, [(Ident,Int)])
sizesModule :: Module -> (Int, [(Ident, Int)])
sizesModule (ModuleName
_,ModuleInfo
m) = 
  let 
    js :: [(Ident, Info)]
js = Map Ident Info -> [(Ident, Info)]
forall k a. Map k a -> [(k, a)]
Map.toList (ModuleInfo -> Map Ident Info
jments ModuleInfo
m) 
    tb :: [(Ident, Int)]
tb = [(Ident
i,Int
k) | (Ident
i,Info
j) <- [(Ident, Info)]
js, let k :: Int
k = Info -> Int
sizeInfo Info
j, Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0]
  in ([(Ident, Int)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Ident, Int)]
tb Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((Ident, Int) -> Int) -> [(Ident, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Ident, Int) -> Int
forall a b. (a, b) -> b
snd [(Ident, Int)]
tb),[(Ident, Int)]
tb)
{-
-- the size of a grammar
sizeGrammar :: Grammar -> Int
sizeGrammar = fst . sizesGrammar
-}
sizesGrammar :: Grammar -> (Int,[(ModuleName,(Int,[(Ident,Int)]))])
sizesGrammar :: Grammar -> (Int, [(ModuleName, (Int, [(Ident, Int)]))])
sizesGrammar Grammar
g = 
  let 
    ms :: [Module]
ms = Grammar -> [Module]
modules Grammar
g 
    mz :: [(ModuleName, (Int, [(Ident, Int)]))]
mz = [(ModuleName
i,Module -> (Int, [(Ident, Int)])
sizesModule Module
m) | m :: Module
m@(ModuleName
i,ModuleInfo
j) <- [Module]
ms]
  in ([(ModuleName, (Int, [(Ident, Int)]))] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(ModuleName, (Int, [(Ident, Int)]))]
mz Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((ModuleName, (Int, [(Ident, Int)])) -> Int)
-> [(ModuleName, (Int, [(Ident, Int)]))] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ((Int, [(Ident, Int)]) -> Int
forall a b. (a, b) -> a
fst ((Int, [(Ident, Int)]) -> Int)
-> ((ModuleName, (Int, [(Ident, Int)])) -> (Int, [(Ident, Int)]))
-> (ModuleName, (Int, [(Ident, Int)]))
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ModuleName, (Int, [(Ident, Int)])) -> (Int, [(Ident, Int)])
forall a b. (a, b) -> b
snd) [(ModuleName, (Int, [(Ident, Int)]))]
mz), [(ModuleName, (Int, [(Ident, Int)]))]
mz)

printSizesGrammar :: Grammar -> String
printSizesGrammar :: Grammar -> String
printSizesGrammar Grammar
g = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ 
  (String
"total" String -> String -> String
+++ Int -> String
forall a. Show a => a -> String
show Int
s)String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
  [ModuleName -> String
forall a. Pretty a => a -> String
render ModuleName
m String -> String -> String
+++ String
"total" String -> String -> String
+++ Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
++++ 
   [String] -> String
unlines [Int -> String -> String
indent Int
2 (Ident -> String
showIdent Ident
j String -> String -> String
+++ Int -> String
forall a. Show a => a -> String
show Int
k) | (Ident
j,Int
k) <- [(Ident, Int)]
js]
     | (ModuleName
m,(Int
i,[(Ident, Int)]
js)) <- [(ModuleName, (Int, [(Ident, Int)]))]
sg
  ]
 where
   (Int
s,[(ModuleName, (Int, [(Ident, Int)]))]
sg) = Grammar -> (Int, [(ModuleName, (Int, [(Ident, Int)]))])
sizesGrammar Grammar
g