Advertisement
Guest User

Untitled

a guest
Jun 30th, 2016
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.79 KB | None | 0 0
  1. {-# LANGUAGE RecordWildCards, OverloadedStrings #-}
  2. import Data.Map (Map)
  3. import qualified Data.Map as M
  4. import Data.Set (Set)
  5. import qualified Data.Set as S
  6. import Control.Monad.State
  7. import Control.Monad.Trans.Either
  8. import Data.List (intersect)
  9. import Data.String
  10.  
  11. data Name = Name String (Maybe Int)
  12. deriving (Show, Eq, Ord)
  13. data Expr = Lit Int
  14. | Var Name
  15. | Ref Name [String]
  16. | Expr :+: Expr
  17. | Expr :*: Expr
  18. | Index Expr Expr
  19. deriving (Show, Eq, Ord)
  20. data Cmd = Decl Name
  21. | Set Expr Expr
  22. | Seq Cmd Cmd
  23. | If Cmd Cmd
  24. | While Cmd
  25. | Eq Expr Expr
  26. | Noop
  27. deriving (Show, Eq)
  28.  
  29. {-
  30. s@(Decl n) =
  31. s@(Set n e) =
  32. s@(Seq s t) =
  33. s@(If s t) =
  34. s@(While s) =
  35. s@(Eq a b) =
  36. s@Noop =
  37. -}
  38. {-
  39. e@(Lit i) =
  40. e@(Var name) =
  41. e@(Ref base fields) =
  42. e@(a :+: b) =
  43. e@(a :*: b) =
  44. e@(Index v i) =
  45. -}
  46.  
  47. instance Num Expr where
  48. fromInteger = Lit . fromInteger
  49. (+) = (:+:)
  50. (*) = (:*:)
  51.  
  52. instance IsString Name where
  53. fromString s = Name s Nothing
  54. instance IsString Expr where
  55. fromString = Var . fromString
  56.  
  57. data S = S
  58. { env :: Map Expr Expr
  59. , scope :: [Name]
  60. , fresh :: Int
  61. }
  62. deriving (Show, Eq)
  63. data S1 = S1
  64. { env1 :: [Map Expr Expr]
  65. , scope1 :: [[Name]]
  66. , fresh1 :: Int
  67. }
  68. deriving (Show, Eq)
  69. initialState = S1 {env1 = [M.empty], scope1 = [[]], fresh1 = 0}
  70.  
  71. type Error = String
  72. type M = EitherT Error (State S1)
  73.  
  74. runM m = runState (runEitherT m) initialState
  75.  
  76. bind :: Expr -> Expr -> M ()
  77. bind name val = lifts $ modify $ \s -> s {env = M.insert name val $ env s}
  78. look :: Expr -> M (Maybe Expr)
  79. look name = lifts $ gets (M.lookup name . env)
  80. declare name = lifts $ modify $ \s -> s {scope = name : scope s}
  81.  
  82. normalize :: Expr -> M Expr
  83. normalize e@(Lit _) = return e
  84. normalize e@(Var name) = do
  85. mv <- look e
  86. case mv of
  87. Nothing -> return e
  88. Just v -> normalize v
  89. normalize e@(Ref base fields) = do
  90. mv <- look e
  91. case mv of
  92. Nothing -> return e
  93. Just v -> normalize v
  94. normalize e@(a :+: b) = do
  95. a <- normalize a
  96. b <- normalize b
  97. return (a :+: b)
  98. normalize e@(Index v i) = do
  99. i <- normalize i
  100. return (Index v i)
  101. -- TODO don't use *
  102. normalize e@(a :*: b) = error "not implemented"
  103.  
  104. terms :: Expr -> [Expr]
  105. terms e@(Lit i) = [e]
  106. terms e@(Var name) = [e]
  107. terms e@(Ref base fields) = [e]
  108. terms e@(a :+: b) = terms a ++ terms b
  109. -- TODO don't use *
  110. terms e@(a :*: b) = error "not implemented"
  111. terms e@(Index v i) = [e]
  112.  
  113. reduce :: Expr -> Expr
  114. reduce = toTerm . toMap
  115. where
  116. toMap :: Expr -> Map Expr Int
  117. toMap = foldr step M.empty . terms
  118. toTerm :: Map Expr Int -> Expr
  119. toTerm m = case map multiply $ M.toList m of
  120. [] -> Lit 0
  121. x:xs -> foldr (+) x xs
  122. -- for prettier output
  123. multiply (e, 0) = Lit 0
  124. multiply (e, 1) = e
  125. multiply (e, c) = Lit c * e
  126. step :: Expr -> Map Expr Int -> Map Expr Int
  127. step (Lit i) map = M.insertWith (+) (Lit 1) i map
  128. step e map = M.insertWith (+) e 1 map
  129.  
  130. -- Approximately detects whether expression involves references to aliased memory.
  131. validLength :: Expr -> M Bool
  132. validLength = fmap validLength' . normalize
  133. validLength' e@(Lit i) = True
  134. -- If an expression fully normalizes to a Var or Ref, this means it was passed as an argument or its value was set by a function call. In this case we assume it is not aliased.
  135. validLength' e@(Var name) = True
  136. validLength' e@(Ref base fields) = True
  137. validLength' e@(a :+: b) = (&&) (validLength' a) (validLength' b)
  138. validLength' e@(a :*: b) = (&&) (validLength' a) (validLength' b)
  139. validLength' e@(Index v i) = False
  140.  
  141. lifts :: State S a -> M a
  142. lifts m = do
  143. S1{..} <- lift get
  144. let (a, S{..}) = runState m (S{env = head env1, scope = head scope1, fresh = fresh1})
  145. lift $ modify $ \s -> s {env1 = env : tail env1 , scope1 = scope : tail scope1 , fresh1 = fresh}
  146. return a
  147.  
  148. push = modify $ \s@(S1{..}) -> s {env1 = head env1 : env1, scope1 = head scope1 : scope1 }
  149. pop = modify $ \s@(S1{..}) -> s {env1 = tail env1, scope1 = tail scope1 }
  150.  
  151. withScope :: M a -> M a
  152. withScope m = do
  153. push
  154. v <- m
  155. pop
  156. return v
  157.  
  158. updates :: Cmd -> [Expr]
  159. updates (Decl n) = []
  160. updates (Set n e) = [n]
  161. updates (Seq s t) = updates s ++ updates t
  162. updates (If s t) = updates s ++ updates t
  163. updates (While s) = updates s
  164. updates (Eq a b) = []
  165. updates Noop = []
  166.  
  167. freshName :: Name -> M Name
  168. freshName (Name str _) = lifts $ do
  169. f <- gets fresh
  170. modify $ \s -> s {fresh = f+1}
  171. return (Name str (Just f))
  172.  
  173. resetVar :: Expr -> M ()
  174. resetVar e@(Var n) = do
  175. f <- freshName n
  176. bind e (Var f)
  177. resetVar e@(Ref n fs) = do
  178. f <- freshName n
  179. bind e (Ref f fs)
  180. resetVars = mapM_ resetVar
  181.  
  182. -- (reduce) arithmetic (normalize) using current value approximations.
  183. simplify :: Expr -> M Expr
  184. simplify = fmap reduce . normalize
  185.  
  186. -- Static value analysis interpreter
  187. step :: Cmd -> M ()
  188. -- Models parameters, calls, uninitialized declarations.
  189. step (Decl name) = do
  190. declare name
  191. resetVar (Var name)
  192. -- Main clause. Binds current approximation to `expr` to `name`.
  193. step (Set name expr) = do
  194. expr <- normalize expr
  195. bind name expr
  196. step (Seq a b) = do
  197. step a
  198. step b
  199. -- `If`/`While` main complication: need to identify program points where values
  200. -- may be unknown (we don't perform any induction or case analysis).
  201. step (If t e) = do
  202. let b1 = updates t
  203. let b2 = updates t
  204. s <- lifts $ gets scope
  205. -- Any variable declared before the If and modified within it has uncertain
  206. -- value after.
  207. let resets = intersect (map Var s) (b1 ++ b2)
  208. withScope $ step t
  209. withScope $ step e
  210. resetVars resets
  211. step (While b) = do
  212. let mod = updates b
  213. s <- lifts $ gets scope
  214. -- Any variable declared before the While and modified within it has
  215. -- uncertain value at the start of the loop body and after the loop.
  216. let resets = intersect (map Var s) mod
  217. withScope $ do
  218. resetVars resets
  219. step b
  220. resetVars resets
  221. -- Assertion clause. Models vector operation type-checking.
  222. step l@(Eq a b) = do
  223. aok <- validLength a
  224. bok <- validLength b
  225. a <- simplify a
  226. b <- simplify b
  227. if aok then return () else left (unlines ["invalid length:", show a])
  228. if bok then return () else left (unlines ["invalid length:", show b])
  229. if (a == b) then return () else left (unlines ["unequal:" , show l , show (a,b)])
  230. step (Noop) = return ()
  231. -- TODO ^ to be more valid (in plover) we need to observe reference creation and
  232. -- invalidate those variables (when the reference is explicitly used or passed
  233. -- to a function).
  234.  
  235. -- Tests --
  236. fromL = foldr Seq Noop
  237. ps =
  238. [ (False, fromL $
  239. [ Decl "n"
  240. , Set "n" 0
  241. , Eq "n" 1
  242. ])
  243. , (True, fromL $
  244. [
  245. ])
  246. , (True, fromL $
  247. [ Decl "n"
  248. , Set "n" 0
  249. , If Noop Noop
  250. , Eq "n" 0
  251. ])
  252. , (False, fromL $
  253. [ Decl "n"
  254. , Set "n" 0
  255. , If (Set "n" 0) Noop
  256. , Eq "n" 0
  257. ])
  258. , (True, fromL $
  259. [ Decl "n"
  260. , Set "n" 0
  261. , Eq "n" 0
  262. , Set "n" 1
  263. , Eq "n" 1
  264. ])
  265. , (False, fromL $
  266. [ Decl "x", Decl "y", Decl "z", Set "x" 0
  267. , While $ fromL $
  268. [ Eq "x" 0
  269. , Set "x" ("x" + 1)
  270. ]
  271. ])
  272. , (False, fromL $
  273. [ Decl "x", Decl "y", Decl "z", Set "x" 0
  274. , While $ fromL $
  275. [ Set "x" ("x" + 1)
  276. ]
  277. , Eq "x" 0
  278. ])
  279. , (True, fromL $
  280. [ Decl "x", Decl "y", Decl "z", Set "x" 0
  281. , While $ fromL $
  282. [ Eq "x" 0
  283. ]
  284. , Eq "x" 0
  285. ])
  286. , (True, fromL $
  287. [ Decl "x", Decl "y", Decl "z"
  288. , While $ fromL $
  289. [ Set "x" ("x" + 1)
  290. ]
  291. ])
  292. , (False, fromL $
  293. [ Decl "x", Decl "y", Decl "z"
  294. , Set "y" "x"
  295. , Set "x" ("x" + 1)
  296. , Set "z" "x"
  297. , Eq "y" "z"
  298. ])
  299. , (True, fromL $
  300. [ Decl "x", Decl "y", Decl "z", Decl "u"
  301. , Set "y" "x"
  302. , Set "x" ("x" + 1)
  303. , Set "w" "x"
  304. , Set "x" ("x" + 1)
  305. , Set "z" "x"
  306. , Eq ("y"+2) "z"
  307. , Eq ("y"+1) "w"
  308. ])
  309. , (True, fromL $
  310. [ Decl "x", Decl "y"
  311. , Set "x" 0
  312. , While $ fromL $
  313. [ Eq "x" 0
  314. ]
  315. , Eq "x" 0
  316. ])
  317. , (False, fromL $
  318. [ Decl "x", Decl "y"
  319. , Set "x" 0
  320. , While $ fromL $
  321. [ Eq "x" 0
  322. , Set "x" ("x" + 1)
  323. ]
  324. ])
  325. , (False, fromL $
  326. [ Decl "x", Decl "y"
  327. , Set "x" 0
  328. , While $ fromL $
  329. [ Set "x" 0
  330. ] -- no check for equivalence of paths
  331. , Eq "x" 0
  332. ])
  333. , (True, fromL $
  334. [ Decl "x", Decl "y"
  335. , Set "x" 0, Set "y" 0
  336. , While $ fromL $
  337. [ Set "x" ("y" + 1)
  338. , Eq "x" ("y" + 1)
  339. , Set "y" ("y" + 1)
  340. , Eq "x" "y"
  341. ]
  342. ])
  343. , (True, fromL $
  344. [ Decl "x"
  345. , Set (Ref "x" []) 0
  346. , Eq (Ref "x" []) 0
  347. ])
  348. , (False, fromL $
  349. [ Decl "x", Eq (Index "x" 0) (Index "x" 0) -- can't assert value of aliased location value
  350. ])
  351. ]
  352.  
  353. main' (i, (ok, p)) = do
  354. let (v, s) = runM (step p)
  355. case v of
  356. Left e -> if ok then putStrLn $ "SHOULD SUCCEED:\n" ++ e else putStrLn "ok"
  357. Right s -> if ok then putStrLn "ok" else putStrLn $ "SHOULD FAIL: " ++ show i
  358. putStrLn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  359. main = mapM_ main' $ zip [0..] ps
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement