69ed7631fe
pulls the arguments out of Definitions (placing them in lambdas).
170 lines
No EOL
5.5 KiB
Haskell
170 lines
No EOL
5.5 KiB
Haskell
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
module SourceSyntax.Rename (renameModule, derename, deprime) where
|
|
|
|
import Control.Arrow (first)
|
|
import Control.Monad (ap, liftM, foldM, mapM, Monad, zipWithM)
|
|
import Control.Monad.State (evalState, State, get, put)
|
|
import Data.Char (isLower,isDigit)
|
|
import qualified Data.Map as Map
|
|
import Unique
|
|
import SourceSyntax.Location as Loc
|
|
import SourceSyntax.Pattern
|
|
import SourceSyntax.Expression
|
|
import SourceSyntax.Declaration hiding (Assoc(..))
|
|
import SourceSyntax.Module
|
|
|
|
derename var
|
|
| isDigit (last var) = reverse . tail . dropWhile isDigit $ reverse var
|
|
| otherwise = var
|
|
|
|
renameModule :: Module t v -> Module t v
|
|
renameModule modul = run (rename Map.empty modul)
|
|
|
|
type Env = Map.Map String String
|
|
|
|
replace :: Env -> String -> String
|
|
replace env v =
|
|
Map.findWithDefault (deprime v) v env
|
|
|
|
class Rename a where
|
|
rename :: Env -> a -> Unique a
|
|
|
|
instance Rename (Module t v) where
|
|
rename env (Module name ex im decls) = do decls' <- renameDecls env decls
|
|
return (Module name ex im decls')
|
|
|
|
instance Rename (Def t v) where
|
|
rename env def =
|
|
case def of
|
|
Def p e ->
|
|
do (p', e', _) <- patternRename env (p,e)
|
|
return (Def p' e')
|
|
TypeAnnotation n t ->
|
|
return (TypeAnnotation (replace env n) t)
|
|
|
|
|
|
instance Rename (Declaration t v) where
|
|
rename env stmt =
|
|
case stmt of
|
|
Definition def -> Definition `liftM` rename env def
|
|
Datatype name args tcs ->
|
|
return $ Datatype name args $ map (first $ replace env) tcs
|
|
TypeAlias n xs t -> return (TypeAlias n xs t)
|
|
ImportEvent js base elm tipe ->
|
|
do base' <- rename env base
|
|
return $ ImportEvent js base' (replace env elm) tipe
|
|
ExportEvent js elm tipe ->
|
|
return $ ExportEvent js (replace env elm) tipe
|
|
|
|
renameDecls env decls =
|
|
do env' <- extends env $ concatMap getNames decls
|
|
mapM (rename env') decls
|
|
where getNames stmt = case stmt of
|
|
--Definition (Def n _) -> [n]
|
|
Datatype _ _ tcs -> map fst tcs
|
|
ImportEvent _ _ n _ -> [n]
|
|
_ -> []
|
|
|
|
instance Rename a => Rename (Located a) where
|
|
rename env (L t s e) = L t s `liftM` rename env e
|
|
|
|
instance Rename (Expr t v) where
|
|
rename env expr =
|
|
let rnm = rename env in
|
|
case expr of
|
|
|
|
Range e1 e2 -> Range `liftM` rnm e1
|
|
`ap` rnm e2
|
|
|
|
Access e x -> Access `liftM` rnm e
|
|
`ap` return x
|
|
|
|
Remove e x -> flip Remove x `liftM` rnm e
|
|
|
|
Insert e x v -> flip Insert x `liftM` rnm e
|
|
`ap` rnm v
|
|
|
|
Modify e fs -> Modify `liftM` rnm e
|
|
`ap` mapM (\(x,e) -> (,) x `liftM` rnm e) fs
|
|
|
|
Record fs -> Record `liftM` mapM frnm fs
|
|
where
|
|
frnm (f,e) = (,) f `liftM` rename env e
|
|
|
|
Binop op@(h:_) e1 e2 ->
|
|
let rop = if isLower h || '_' == h
|
|
then replace env op
|
|
else op
|
|
in Binop rop `liftM` rnm e1
|
|
`ap` rnm e2
|
|
|
|
Lambda pattern e -> do
|
|
(pattern', env') <- patternExtend env pattern
|
|
Lambda pattern' `liftM` rename env' e
|
|
|
|
App e1 e2 -> App `liftM` rnm e1
|
|
`ap` rnm e2
|
|
|
|
MultiIf ps -> MultiIf `liftM` mapM grnm ps
|
|
where grnm (b,e) = (,) `liftM` rnm b
|
|
`ap` rnm e
|
|
|
|
Let defs e -> renameLet env defs e
|
|
|
|
Var x -> return $ Var (replace env x)
|
|
|
|
Data name es -> Data name `liftM` mapM rnm es
|
|
|
|
ExplicitList es -> ExplicitList `liftM` mapM rnm es
|
|
|
|
Case e cases -> Case `liftM` rnm e
|
|
`ap` mapM (liftM drop3rd . patternRename env) cases
|
|
where
|
|
drop3rd (a,b,c) = (a,b)
|
|
|
|
_ -> return expr
|
|
|
|
deprime = map (\c -> if c == '\'' then '$' else c)
|
|
|
|
extend :: Env -> String -> Unique (String, Env)
|
|
extend env x = do
|
|
n <- guid
|
|
let rx = deprime x ++ "_" ++ show n
|
|
return (rx, Map.insert x rx env)
|
|
|
|
extends :: Env -> [String] -> Unique Env
|
|
extends env xs = foldM (\e x -> liftM snd $ extend e x) env xs
|
|
|
|
patternExtend :: Env -> Pattern -> Unique (Pattern, Env)
|
|
patternExtend env pattern =
|
|
case pattern of
|
|
PLiteral _ -> return (pattern, env)
|
|
PAnything -> return (pattern, env)
|
|
PVar x -> first PVar `liftM` extend env x
|
|
PAlias x p -> do
|
|
(x', env') <- extend env x
|
|
(p', env'') <- patternExtend env' p
|
|
return (PAlias x' p', env'')
|
|
PData name ps ->
|
|
first (PData name . reverse) `liftM` foldM f ([], env) ps
|
|
where f (rps,env') p = do (rp,env'') <- patternExtend env' p
|
|
return (rp:rps, env'')
|
|
PRecord fs ->
|
|
return (pattern, Map.union (Map.fromList $ map (\f -> (f,f)) fs) env)
|
|
|
|
patternRename :: Env -> (Pattern, LExpr t v) -> Unique (Pattern, LExpr t v, Env)
|
|
patternRename env (pattern,expr) = do
|
|
(pattern',env') <- patternExtend env pattern
|
|
expr' <- rename env' expr
|
|
return (pattern', expr', env')
|
|
|
|
renameLet env defs e =
|
|
do (env', ps') <- foldM addPattern (env, []) (map fst defPairs)
|
|
bodies <- mapM (rename env') (map snd defPairs)
|
|
Let (zipWith Def ps' bodies) `liftM` rename env' e
|
|
where
|
|
defPairs = map (\(Def p e) -> (p,e)) defs
|
|
|
|
addPattern (env,ps) pattern =
|
|
do (pattern', _, env') <- patternRename env (pattern, Loc.none (Var ""))
|
|
return (env', pattern' : ps) |