mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-20 08:32:50 -06:00
Remove more useless pattern matching and variable bindings in transfer compilation.
This commit is contained in:
@@ -36,8 +36,7 @@ declsToCore_ = numberMetas
|
|||||||
>>> optimize
|
>>> optimize
|
||||||
|
|
||||||
optimize :: [Decl] -> C [Decl]
|
optimize :: [Decl] -> C [Decl]
|
||||||
optimize = removeUnusedVariables
|
optimize = removeUselessMatch
|
||||||
>>> removeUselessMatch
|
|
||||||
>>> betaReduce
|
>>> betaReduce
|
||||||
|
|
||||||
newState :: CState
|
newState :: CState
|
||||||
@@ -263,7 +262,7 @@ betaReduce = return . map f
|
|||||||
_ -> composOp f t
|
_ -> composOp f t
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Remove useless pattern matching.
|
-- * Remove useless pattern matching and variable binding.
|
||||||
--
|
--
|
||||||
|
|
||||||
removeUselessMatch :: [Decl] -> C [Decl]
|
removeUselessMatch :: [Decl] -> C [Decl]
|
||||||
@@ -271,53 +270,83 @@ removeUselessMatch = return . map f
|
|||||||
where
|
where
|
||||||
f :: Tree a -> Tree a
|
f :: Tree a -> Tree a
|
||||||
f x = case x of
|
f x = case x of
|
||||||
-- replace \x -> case x of { y -> e } with \y -> e,
|
|
||||||
-- if x is not free in e
|
|
||||||
-- FIXME: this checks the result of the recursive call,
|
|
||||||
-- can we do something about this?
|
|
||||||
EAbs (VVar x) b ->
|
EAbs (VVar x) b ->
|
||||||
case f b of
|
case f b of
|
||||||
|
-- replace \x -> case x of { y -> e } with \y -> e,
|
||||||
|
-- if x is not free in e
|
||||||
ECase (EVar x') [Case (PVar y) e]
|
ECase (EVar x') [Case (PVar y) e]
|
||||||
| x' == x && not (x `isFreeIn` e)
|
| x' == x && not (x `isFreeIn` e)
|
||||||
-> f (EAbs (VVar y) e)
|
-> f (EAbs (VVar y) e)
|
||||||
|
-- replace unused variable in lambda with wild card
|
||||||
|
e | not (x `isFreeIn` e) -> f (EAbs VWild e)
|
||||||
e -> EAbs (VVar x) e
|
e -> EAbs (VVar x) e
|
||||||
|
-- replace unused variable in pi with wild card
|
||||||
|
EPi (VVar x) t e ->
|
||||||
|
let e' = f e
|
||||||
|
v = if not (x `isFreeIn` e') then VWild else VVar x
|
||||||
|
in EPi v (f t) e'
|
||||||
|
-- replace unused variables in case patterns with wild cards
|
||||||
|
Case p e ->
|
||||||
|
let e' = f e
|
||||||
|
p' = f (removeUnusedVarPatts (freeVars e') p)
|
||||||
|
in Case p' e'
|
||||||
-- for value declarations without patterns, compilePattDecls
|
-- for value declarations without patterns, compilePattDecls
|
||||||
-- generates pattern matching on the empty record, remove these
|
-- generates pattern matching on the empty record, remove these
|
||||||
ECase (ERec []) [Case (PRec []) e] -> f e
|
ECase (ERec []) [Case (PRec []) e] -> f e
|
||||||
-- if the pattern matching is on a single field of a record expression
|
-- if the pattern matching is on a single field of a record expression
|
||||||
-- with only one field, there is no need to wrap it in a record
|
-- with only one field, there is no need to wrap it in a record
|
||||||
ECase (ERec [FieldValue x e]) cs | all (isSingleFieldPattern x) [ p | Case p _ <- cs]
|
ECase (ERec [FieldValue x e]) cs | all (isSingleFieldPattern x) (casePatterns cs)
|
||||||
-> f (ECase e [ Case p r | Case (PRec [FieldPattern _ p]) r <- cs ])
|
-> f (ECase e [ Case p r | Case (PRec [FieldPattern _ p]) r <- cs ])
|
||||||
-- In cases: remove record field patterns which only bind unused variables
|
-- for all fields in record matching where all patterns just
|
||||||
Case (PRec fps) e -> Case (f (PRec (fps \\ unused))) (f e)
|
-- bind variables, substitute in the field value (if it is a variable)
|
||||||
where unused = [fp | fp@(FieldPattern l (PVar id)) <- fps,
|
-- in the right hand sides.
|
||||||
not (id `isFreeIn` e)]
|
ECase (ERec fs) cs | all isPRec (casePatterns cs) ->
|
||||||
|
let g (FieldValue f v@(EVar _):fs) xs
|
||||||
|
| all (onlyBindsFieldToVariable f) (casePatterns xs)
|
||||||
|
= g fs (map (inlineField f v) xs)
|
||||||
|
g (f:fs) xs = let (fs',xs') = g fs xs in (f:fs',xs')
|
||||||
|
g [] xs = ([],xs)
|
||||||
|
inlineField f v (Case (PRec fps) e) =
|
||||||
|
let p' = PRec [fp | fp@(FieldPattern f' _) <- fps, f' /= f]
|
||||||
|
ss = zip (fieldPatternVars f fps) (repeat v)
|
||||||
|
in Case p' (substs ss e)
|
||||||
|
(fs',cs') = g fs cs
|
||||||
|
x' = ECase (ERec fs') cs'
|
||||||
|
in if length fs' < length fs then f x' else composOp f x'
|
||||||
-- Remove wild card patterns in record patterns
|
-- Remove wild card patterns in record patterns
|
||||||
PRec fps -> PRec (map f (fps \\ wildcards))
|
PRec fps -> PRec (map f (fps \\ wildcards))
|
||||||
where wildcards = [fp | fp@(FieldPattern _ PWild) <- fps]
|
where wildcards = [fp | fp@(FieldPattern _ PWild) <- fps]
|
||||||
_ -> composOp f x
|
_ -> composOp f x
|
||||||
|
|
||||||
|
removeUnusedVarPatts :: Set Ident -> Tree a -> Tree a
|
||||||
|
removeUnusedVarPatts keep x = case x of
|
||||||
|
PVar id | not (id `Set.member` keep) -> PWild
|
||||||
|
_ -> composOp (removeUnusedVarPatts keep) x
|
||||||
|
|
||||||
isSingleFieldPattern :: Ident -> Pattern -> Bool
|
isSingleFieldPattern :: Ident -> Pattern -> Bool
|
||||||
isSingleFieldPattern x p = case p of
|
isSingleFieldPattern x p = case p of
|
||||||
PRec [FieldPattern y _] -> x == y
|
PRec [FieldPattern y _] -> x == y
|
||||||
_ -> False
|
_ -> False
|
||||||
--
|
|
||||||
-- * Change varibles which are not used to wildcards.
|
|
||||||
--
|
|
||||||
|
|
||||||
removeUnusedVariables :: [Decl] -> C [Decl]
|
casePatterns :: [Case] -> [Pattern]
|
||||||
removeUnusedVariables = return . map f
|
casePatterns cs = [p | Case p _ <- cs]
|
||||||
where
|
|
||||||
f :: Tree a -> Tree a
|
isPRec :: Pattern -> Bool
|
||||||
f x = case x of
|
isPRec (PRec _) = True
|
||||||
EAbs (VVar id) e | not (id `isFreeIn` e) -> EAbs VWild (f e)
|
isPRec _ = False
|
||||||
EPi (VVar id) t e | not (id `isFreeIn` e) -> EPi VWild (f t) (f e)
|
|
||||||
Case p e -> Case (g (freeVars e) p) (f e)
|
-- | Checks if given pattern is a record pattern, and matches the field
|
||||||
_ -> composOp f x
|
-- with just a variable, with a wild card, or not at all.
|
||||||
-- replace pattern variables not in the given set with wildcards
|
onlyBindsFieldToVariable :: Ident -> Pattern -> Bool
|
||||||
g :: Set Ident -> Tree a -> Tree a
|
onlyBindsFieldToVariable f (PRec fps) =
|
||||||
g keep x = case x of
|
all isVar [p | FieldPattern f' p <- fps, f == f']
|
||||||
PVar id | not (id `Set.member` keep) -> PWild
|
where isVar (PVar _) = True
|
||||||
_ -> composOp (g keep) x
|
isVar PWild = True
|
||||||
|
isVar _ = False
|
||||||
|
onlyBindsFieldToVariable _ _ = False
|
||||||
|
|
||||||
|
fieldPatternVars :: Ident -> [FieldPattern] -> [Ident]
|
||||||
|
fieldPatternVars f fps = [p | FieldPattern f' (PVar p) <- fps, f == f']
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Remove simple syntactic sugar.
|
-- * Remove simple syntactic sugar.
|
||||||
@@ -376,17 +405,24 @@ ifBool c t e = ECase c [Case (PCons (Ident "True") []) t,
|
|||||||
--
|
--
|
||||||
|
|
||||||
subst :: Ident -> Exp -> Exp -> Exp
|
subst :: Ident -> Exp -> Exp -> Exp
|
||||||
subst x e = f
|
subst x e = substs [(x,e)]
|
||||||
|
|
||||||
|
-- | Simultaneuous substitution
|
||||||
|
substs :: [(Ident, Exp)] -> Exp -> Exp
|
||||||
|
substs ss = f (Map.fromList ss)
|
||||||
where
|
where
|
||||||
f :: Tree a -> Tree a
|
f :: Map Ident Exp -> Tree a -> Tree a
|
||||||
f t = case t of
|
f ss t | Map.null ss = t
|
||||||
ELet defs exp3 | x `Set.member` letDefBinds defs ->
|
f ss t = case t of
|
||||||
ELet [ LetDef id (f exp1) exp2 | LetDef id exp1 exp2 <- defs] exp3
|
ELet ds e3 ->
|
||||||
Case p e | x `Set.member` binds p -> t
|
ELet [LetDef id (f ss e1) (f ss' e2) | LetDef id e1 e2 <- ds] (f ss' e3)
|
||||||
EAbs (VVar id) _ | x == id -> t
|
where ss' = ss `mapMinusSet` letDefBinds ds
|
||||||
EPi (VVar id) exp1 exp2 | x == id -> EPi (VVar id) (f exp1) exp2
|
Case p e -> Case p (f ss' e) where ss' = ss `mapMinusSet` binds p
|
||||||
EVar i | i == x -> e
|
EAbs (VVar id) e -> EAbs (VVar id) (f ss' e) where ss' = Map.delete id ss
|
||||||
_ -> composOp f t
|
EPi (VVar id) e1 e2 ->
|
||||||
|
EPi (VVar id) (f ss e1) (f ss' e2) where ss' = Map.delete id ss
|
||||||
|
EVar i -> Map.findWithDefault t i ss
|
||||||
|
_ -> composOp (f ss) t
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Abstract syntax utilities
|
-- * Abstract syntax utilities
|
||||||
@@ -512,3 +548,6 @@ infixl 1 >>>
|
|||||||
|
|
||||||
(>>>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
|
(>>>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
|
||||||
f >>> g = (g =<<) . f
|
f >>> g = (g =<<) . f
|
||||||
|
|
||||||
|
mapMinusSet :: Ord k => Map k a -> Set k -> Map k a
|
||||||
|
mapMinusSet m s = m Map.\\ (Map.fromList [(x,()) | x <- Set.toList s])
|
||||||
|
|||||||
@@ -14,9 +14,5 @@ natToInt : Nat -> Int
|
|||||||
natToInt Zero = 0
|
natToInt Zero = 0
|
||||||
natToInt (Succ n) = 1 + natToInt n
|
natToInt (Succ n) = 1 + natToInt n
|
||||||
|
|
||||||
plus : Nat -> Nat -> Nat
|
|
||||||
plus Zero y = y
|
|
||||||
plus (Succ x) y = Succ (plus x y)
|
|
||||||
|
|
||||||
intToNat : Int -> Nat
|
intToNat : Int -> Nat
|
||||||
intToNat n = if n == 0 then Zero else Succ (intToNat (n-1))
|
intToNat n = if n == 0 then Zero else Succ (intToNat (n-1))
|
||||||
|
|||||||
Reference in New Issue
Block a user