@@ -1,73 +1,97 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1module Rename (rename) where
2module Rename (rename) where
4import Control.Arrow (first)
5import Control.Arrow (first)
5−import Control.Monad.State
6+import Control.Monad (ap, liftM, foldM, mapM, Monad)
7+import Control.Monad.State (evalState, State, get, put)
6import Data.Char (isLower)
8import Data.Char (isLower)
7−import Data.List (mapAccumL)
8−import Data.Functor.Identity
10−rename expr = evalState (rename' id expr) 0
10+-- Wrapper around State monad.
11+newtype GuidCounter a = GC { runGC :: State Int a }
14+-- Get the next GUID, incrementing the counter.
12−guid :: State Int Int
15+guid :: GuidCounter Int
13−guid = do n <- get
16+guid = GC $ do n <- get
14− put (n+1)
17+ put (n + 1)
20+rename :: Expr -> Expr
21+rename expr = evalState (runGC $ rename' id expr) 0
23+rename' :: (String -> String) -> Expr -> GuidCounter Expr
17rename' env expr =
24rename' env expr =
18 case expr of
25 case expr of
19− Range e1 e2 -> do
27+ Range e1 e2 -> Range `liftM` rnm e1
20− re1 <- rename' env e1; re2 <- rename' env e2
28+ `ap` rnm e2
21− return $ Range re1 re2
29+
22− Access e x -> do
30+ Access e x -> Access `liftM` rnm e
23− re <- rename' env e
31+ `ap` return x
24− return $ Access re x
32+
25− Binop op e1 e2 ->
33+ Binop op@(h:_) e1 e2 ->
26− do let rop = if isLower (head op) || '_' == head op then env op else op
34+ let rop = if isLower h || '_' == h
27− re1 <- rename' env e1; re2 <- rename' env e2
35+ then env op
28− return $ Binop rop re1 re2
36+ else op
37+ in Binop rop `liftM` rnm e1
29− Lambda x e -> do (rx, env') <- extend env x
41+ (rx, env') <- extend env x
30− rename' env' e >>= return . Lambda rx
42+ Lambda rx `liftM` rename' env' e
31− App e1 e2 -> do
44+ App e1 e2 -> App `liftM` rnm e1
32− re1 <- rename' env e1; re2 <- rename' env e2
45+ `ap` rnm e2
33− return $ App re1 re2
46+
34− If e1 e2 e3 -> do
47+ If e1 e2 e3 -> If `liftM` rnm e1
35− re1 <- rename' env e1; re2 <- rename' env e2; re3 <- rename' env e3
48+ `ap` rnm e2
36− return $ If re1 re2 re3
49+ `ap` rnm e3
37− Lift e es -> do
51+ Lift e es -> Lift `liftM` rnm e
38− re <- rename' env e
52+ `ap` mapM rnm es
39− mapM (rename' env) es >>= return . Lift re
53+
40− Fold e1 e2 e3 -> do
54+ Fold e1 e2 e3 -> Fold `liftM` rnm e1
41− re1 <- rename' env e1; re2 <- rename' env e2; re3 <- rename' env e3
55+ `ap` rnm e2
42− return $ Fold re1 re2 re3
56+ `ap` rnm e3
43− Async e -> rename' env e >>= return . Async
57+
58+ Async e -> Async `liftM` rnm e
44 Let defs e -> do
60 Let defs e -> do
45 let (vs,es) = unzip defs
61 let (vs,es) = unzip defs
46− env' <- foldM (\acc x -> extend acc x >>= return . snd) env vs
62+ env' <- foldM (\acc x -> snd `liftM` extend acc x) env vs
47 es' <- mapM (rename' env') es; re <- rename' env' e
63 es' <- mapM (rename' env') es; re <- rename' env' e
48 return $ Let (zip (map env' vs) es') re
64 return $ Let (zip (map env' vs) es') re
49 Var x -> return . Var $ env x
66 Var x -> return . Var $ env x
50− Data name es -> mapM (rename' env) es >>= return . Data name
67+
68+ Data name es -> Data name `liftM` mapM rnm es
51− Case e cases -> do
70+ Case e cases -> Case `liftM` rnm e
52− re <- rename' env e
71+ `ap` mapM (patternRename env) cases
53− mapM (pattern_rename env) cases >>= return . (Case re)
72+
54 _ -> return expr
73 _ -> return expr
75+ where rnm = rename' env
77+extend :: (String -> String) -> String -> GuidCounter (String, String -> String)
56extend env x = do
78extend env x = do
58 let rx = x ++ "_" ++ show n
80 let rx = x ++ "_" ++ show n
59− return (rx, (\y -> if y == x then rx else env y))
81+ return (rx, \y -> if y == x then rx else env y)
83+patternExtend :: Pattern -> (String -> String) -> GuidCounter (Pattern, String -> String)
61−pattern_extend pattern env =
84+patternExtend pattern env =
62 case pattern of
85 case pattern of
63 PAnything -> return (PAnything, env)
86 PAnything -> return (PAnything, env)
64− PVar x -> extend env x >>= return . first PVar
87+ PVar x -> first PVar `liftM` extend env x
65 PData name ps ->
88 PData name ps ->
66− foldM f ([],env) ps >>= return . first (PData name . reverse)
89+ first (PData name . reverse) `liftM` foldM f ([], env) ps
67− where f (rps,env') p = do (rp,env'') <- pattern_extend p env'
90+ where f (rps,env') p = do (rp,env'') <- patternExtend p env'
68 return (rp:rps, env'')
91 return (rp:rps, env'')
70−pattern_rename env (p,e) = do
93+patternRename :: (String -> String) -> (Pattern, Expr) -> GuidCounter (Pattern, Expr)
94+patternRename env (p,e) = do
71− (rp,env') <- pattern_extend p env
95+ (rp,env') <- patternExtend p env
72 re <- rename' env' e
96 re <- rename' env' e
73− return (rp,re)
97+ return (rp,re)