module CaseHelp(Pattern(..), alt2fun,getTrans,sortCon,sortInt,splitPattern,varExp,varExpT
,dropPatAs, isExpVar, needLet) where
import Syntax
import PosCode
import State
import IntState
import qualified Data.Map as Map
import CaseLib
import SyntaxPos
import SyntaxUtil
import Id
alt2fun :: Alt Id -> Fun Id
alt2fun (Alt pat gdexps decls) = Fun [pat] gdexps decls
noVar :: Id
noVar = error "noVar"
-- The following two functions could be simplified no.
-- the expression is always simple if trans isn't empty.
varExpT :: [a] -> PosExp -> CaseFun ([a],Id,PosExp->PosExp,PosExp)
varExpT [] e =
unitS ([],noVar,id,e)
varExpT trans e@(PosVar pos v) =
unitS (trans,v,id,e)
varExpT trans e =
caseUnique >>>= \ v ->
let pos = getPos e
in unitS (trans,v,PosExpLet False pos [(v,PosLambda pos LamFLIntro [] [] e)],PosVar pos v)
varExp :: PosExp -> CaseFun (Id,PosExp->PosExp,PosExp)
varExp e@(PosVar pos v) =
unitS (v,id,e)
varExp e =
caseUnique >>>= \ v ->
let pos = getPos e
in unitS (v,PosExpLet False pos [(v,PosLambda pos LamFLIntro [] [] e)],PosVar pos v)
getTrans :: ExpI -> [Id]
getTrans (ExpVar _ ident) = [ident]
getTrans (PatAs _ ident p) = ident : getTrans p
getTrans _ = []
isIf :: ExpI -> Bool
isIf p = not (isVar p || isCon p || isExpInt p || isNK p || isExpIrr p)
data Pattern =
PatternVar [(Exp Id,Fun Id)]
| PatternCon [(Exp Id,Fun Id)]
| PatternInt Bool [(Exp Id,Fun Id)]
| PatternNK [(Exp Id,Fun Id)]
| PatternIf [(Exp Id,Fun Id)]
| PatternIrr (Exp Id,Fun Id)
patternTypes :: [(ExpI->Bool ,[(ExpI,Fun Id)] -> [Pattern])]
patternTypes =
[(isVar,(:[]).PatternVar)
,(isCon,(:[]).PatternCon)
,(isExpInt,(:[]).PatternInt True)
,(isExpChar,(:[]).PatternInt False)
,(isNK,(:[]).PatternNK)
,(isExpIrr,map PatternIrr)
,(isIf,(:[]).PatternIf)]
splitPattern :: (ExpI,ExpI) -> IntState -> [Fun Id] -> [Pattern]
splitPattern list state funs =
(split patternTypes (map (splitFuns list state) funs))
where
split pt [] = []
split [] funs = split patternTypes funs
split ((p,t):pt) funs =
case span (p . dropPatAs . fst) funs of
([],funs) -> split pt funs
(vs,funs) -> t vs ++ split pt funs
splitFuns :: (ExpI,ExpI) -> IntState -> Fun Id -> (ExpI,Fun Id)
splitFuns list state (Fun (p:ps) gdexps decls) =
(simplifyPat list state p,Fun ps gdexps decls)
simplifyPat :: (ExpI,ExpI) -> IntState -> ExpI -> ExpI
simplifyPat list state (ExpList pos ls) =
case ls of
[] -> fst list
(x:xs) -> ExpApplication pos [snd list,x,ExpList pos xs]
simplifyPat list state (ExpLit pos (LitString b str)) =
case str of
[] -> fst list
(x:xs) -> ExpApplication pos [snd list, ExpLit pos (LitInt b (fromEnum x)),ExpLit pos (LitString b xs)]
-- simplifyPat list state (ExpLit pos (LitChar b i)) = ExpLit pos (LitInt b (fromEnum i))
simplifyPat list state (PatAs pos ident pat) = PatAs pos ident (simplifyPat list state pat)
simplifyPat list state (ExpApplication pos (ExpApplication _ es':es)) = ExpApplication pos (map (simplifyPat list state) (es'++es))
simplifyPat list state (ExpDict pat) = simplifyPat list state pat
simplifyPat list state pat = pat
sortInt :: [(ExpI,Fun Id)] -> [(Int,[Fun Id])]
sortInt funs =
(stableSort
.map ( \ (pat,fun) -> (getInt pat,fun))
) funs
where
getInt (PatAs _ _ p) = getInt p
getInt (ExpLit _ (LitInt b i)) = i
getInt (ExpLit _ (LitChar b i)) = fromEnum i
sortCon :: [(ExpI,Fun Id)] -> [(Id,[([Pos], Fun Id)])]
sortCon funs =
(stableSort
. map ( \ (pat,Fun pats gdexps decls) ->
case getConArg pat of
(con,args) -> (con,(map getPos args,Fun (args++pats) gdexps decls)))
) funs
where
getConArg (ExpCon _ con) = (con,[])
getConArg (PatAs _ _ p) = getConArg p
getConArg (ExpApplication _ (ExpCon _ con:ps)) = (con,ps)
stableSort :: Ord a => [(a, b)] -> [(a, [b])]
stableSort xs = -- I hope !!
let add (c,f) t = Map.insertWith (++) c [f] t
in Map.toList (foldr add Map.empty xs)
needLet :: Pattern -> Bool
needLet (PatternVar patfuns) = any (not . null . getTrans . fst) patfuns
needLet (PatternCon patfuns) = any (not . null . getTrans . fst) patfuns
needLet (PatternInt _ patfuns) = any (not . null . getTrans . fst) patfuns
needLet (PatternNK patfuns) = any (not . null . getTrans . fst) patfuns
needLet (PatternIf patfuns) = any (not . null . getTrans . fst) patfuns
needLet (PatternIrr (pat,fun)) = (not . null . getTrans) pat
|