Advertisement
Guest User

Untitled

a guest
Feb 28th, 2020
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.08 KB | None | 0 0
  1. module Renaming(rename)where
  2.  
  3.  
  4. import Data.List (findIndex)
  5. import Control.Monad.State
  6.  
  7. import Type
  8. import Vars
  9. import Subst
  10.  
  11.  
  12. -- | State for a list of variablenames.
  13. type VarState a = State [VarName] a
  14.  
  15.  
  16. -- | 'rename' takes a list of forbidden variablenames and a Rule. It then renames
  17. -- all variables in the rule by using 'freshVars' and avoiding the forbidden names.
  18. rename :: [VarName] -> Rule -> Rule
  19. rename f r = let f' = (allVars r) ++ f -- add all varnames from thr rule to forbidden
  20. r'@(Rule t ts) = replaceUnder r f' -- rename all underscores
  21. sub = getSub f ((allVars r') ++ f') -- get substitutions from old varnames to renamed varnames
  22. in Rule (apply sub t) (map (apply sub) ts) -- apply substitution to rename vars
  23.  
  24. -- | 'replaceUnder' takes a Rule and and a list of forbidden variablenames and
  25. -- calls evalState which calls 'replaceS' and adds alls varnames to the forbidden list
  26. replaceUnder :: Rule -> [VarName] -> Rule
  27. replaceUnder r vs = evalState (replaceS r) $ (allVars r) ++ vs
  28.  
  29. -- | 'replaceS' takes a Rule and replaces all underscores in the variablenames
  30. -- of the rule with fitting names avoiding the forbidden names.
  31. replaceS :: Rule -> VarState Rule
  32. replaceS (Rule t ts) = do t' <- replaceT t -- check if t is an underscore and if needed replace it
  33. -- map over the list of terms and replace each underscore in any term
  34. ts' <- mapM replaceT ts
  35. return (Rule t' ts') -- return rule with renamed underscores
  36. where
  37. -- | 'replaceT' checks if a Term is an underscore or contains an underscore.
  38. -- If it does it replaces the underscore by getting the list of forbidden
  39. -- variablenames, using 'getVars'' to get a new variablename that is valid,
  40. -- saving the new name and the orginial forbidden list and returning the new name.
  41. replaceT :: Term -> VarState Term
  42. replaceT (Var x) = if x == "_"
  43. then do -- varname is "_"„
  44. vs <- get -- get list of forbidden names
  45. let new = ((getVars' 0 1 vs) !! 0) -- get new valid name
  46. put (new:vs) -- add new name to forbidden list
  47. return (Var new) -- return new name
  48. else return (Var x) -- varname not "_"
  49. replaceT (Comb c cs) = do x <- mapM replaceT cs -- replace every underscore in the list of terms
  50. return (Comb c x) -- return comb with renamed list of terms
  51.  
  52. -- | 'replaceUnderscores' takes a Rule and a list of forbidden variablenames and
  53. -- renames all variables in the Rule avoiding the forbidden and the old names.
  54. replaceUnderscores :: Rule -> [VarName] -> Rule
  55. replaceUnderscores (Rule r rs) badVars =
  56. let (_, rs') = replaceRecL badVars (r:rs)
  57. in Rule (head rs')(drop 1 rs')
  58.  
  59. where replaceRec :: [VarName] -> Term -> ([VarName], Term)
  60. replaceRec vs (Var x) = if x == "_"
  61. then let new = (getVars' 0 1 vs) !! 0
  62. in ((new:vs), (Var new))
  63. else (vs,(Var x))
  64. replaceRec vs (Comb c []) = (vs, Comb c [])
  65. replaceRec vs (Comb c t) = let (vs', t') = replaceRecL vs t
  66. in (vs', (Comb c t'))
  67.  
  68. replaceRecL :: [VarName] -> [Term] -> ([VarName], [Term])
  69. replaceRecL vs [] = (vs, [])
  70. replaceRecL vs (t:ts) = let (vs', t') = replaceRec vs t
  71. (vs'', ts') = replaceRecL vs' ts
  72. in (vs'', (t':ts'))
  73.  
  74. -- | 'getSub' takes a list of variablenames and a list of forbidden variablenames
  75. -- and creates a substitution.
  76. getSub :: [VarName] -> [VarName] -> Subst
  77. getSub oVars f = let f' = altVars $ oVars ++ f -- add new varnames, and original varnames to the forbidden list, get new var names
  78. -- create substitution from old name to new names, compose all substitutions into one with foldl
  79. in foldl compose empty $ zipWith (\old new -> single old (Var new)) oVars f'
  80.  
  81. -- | 'altVars' takes a list of variablenames and returns a list of new alternative variables.
  82. altVars :: [VarName] -> [VarName]
  83. altVars xs = getVars' 0 (length xs) xs
  84.  
  85. -- | 'getVars'' takes an index, a length and a list of variablenames. It uses
  86. -- 'freshVars' to get a list of new names which are completely different from the old list.
  87. getVars' :: Int -> Int -> [VarName] -> [VarName]
  88. getVars' i n xs = let fVars = drop i $ take (i+n) freshVars -- use drop and take to specify which indices get taken
  89. -- find the last index where a variable is also an element of the forbidden names
  90. in case findIndex (\x -> elem x xs) (reverse fVars) of
  91. -- if there is an index get new varnames starting at that index
  92. (Just x) -> getVars' (i+(n-x)) n xs
  93. -- if not return the list of new names
  94. (Nothing) -> fVars
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement