1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
module FlatCurry.NormalizeLet ( normalizeLet ) where

import Data.SCC          ( scc )
import FlatCurry.Goodies ( allVars )
import FlatCurry.Types

--- Normalize all let expressions occurring in an expression
--- by transforming each let expression into a hierarchical let expression
--- according to the dependencies of the bindings.
--- For instance,
---
---     let { x = f y ; y = g z} in e
---
--- is transformed into
---
---     let { y = g z} in let { x = f y} in e
---
normalizeLet :: Expr -> Expr
normalizeLet exp = case exp of
  Var _         -> exp
  Lit _         -> exp
  Comb ct qf es -> Comb ct qf (map normalizeLet es)
  Let bs e      -> foldr Let e (sortLetBindings bs)
  Free vs e     -> Free vs (normalizeLet e)
  Or e1 e2      -> Or (normalizeLet e1) (normalizeLet e2)
  Case ct be bs -> Case ct (normalizeLet be)
                        (map (\ (Branch p e) -> Branch p (normalizeLet e)) bs)
  Typed e t     -> Typed (normalizeLet e) t

-- Sort a list of let bindings into strongly connected compontents
-- sorted by the dependencies of the defined variables.
sortLetBindings :: [(Int,Expr)] -> [[(Int,Expr)]]
sortLetBindings bs = scc definedBy usedIn bs
 where
  definedBy (v,_) = [v]

  usedIn (_,e) = filter (`elem` map fst bs) (allVars e)