1
1
mirror of https://github.com/thma/LtuPatternFactory.git synced 2024-11-30 02:03:47 +03:00

clean up Aspects example

This commit is contained in:
thma 2019-01-13 21:08:13 +01:00
parent 866f5b3ac5
commit e6a142138c
4 changed files with 31 additions and 21 deletions

View File

@ -35,6 +35,8 @@ executable LtuPatternFactory
, DependencyInjection
, CheapskateRenderer
, CMarkGFMRenderer
, AspectPascal
, MiniPascal
main-is: Main.hs
default-language: Haskell2010
@ -74,6 +76,8 @@ test-suite LtuPatternFactory-Demo
, DependencyInjection
, CheapskateRenderer
, CMarkGFMRenderer
, AspectPascal
, MiniPascal
hs-source-dirs: src
main-is: Main.hs

View File

@ -1,11 +1,12 @@
{-# LANGUAGE FlexibleContexts #-}
module Aspects1 where
module AspectPascal where
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Writer
import Data.Map (Map, fromList)
import qualified Data.Map as Map (lookup, insert)
import Aspects (Id, IExp (..), BExp (..), Stmt (..), Store (..), program, lookup', demo, getVar, setVar)
import Data.Map (Map)
import qualified Data.Map as Map (lookup, insert, fromList)
import MiniPascal (Id, IExp (..), BExp (..), Stmt (..), Store (..)
, program, demo, getVar, setVar)
data JoinPointDesc = Get Id | Set Id
@ -29,15 +30,16 @@ includes _ _ = False
data Advice = Before PointCut Stmt
| After PointCut Stmt
-- the countSets Advice traces each setting of a variable and increments the counter "setters"
countSets = After ((Setter :&&: (NotAt (AtVar "setters"))) :&&: (NotAt (AtVar "getters")))
("setters" := (IVar "setters" :+: Lit 1))
-- the countGets Advice traces each lookup of a variable and increments the counter "getters"
countGets = After ((Getter :&&: (NotAt (AtVar "setters"))) :&&: (NotAt (AtVar "getters")))
("getters" := (IVar "getters" :+: Lit 1))
type Aspects = [Advice]
iexp :: IExp -> ReaderT Aspects (State Store) Int
iexp (Lit n) = return n
iexp (e1 :+: e2) = liftM2 (+) (iexp e1) (iexp e2)
@ -68,6 +70,7 @@ stmt (While b t) = loop
x <- bexp b
when x $ stmt t >> loop
withAdvice :: JoinPointDesc -> ReaderT Aspects (State Store) b -> ReaderT Aspects (State Store) b
withAdvice d c = do
aspects <- ask
mapM_ stmt (before d aspects)
@ -79,12 +82,11 @@ before, after :: JoinPointDesc -> Aspects -> [Stmt]
before d as = [s | Before c s <- as, includes c d]
after d as = [s | After c s <- as, includes c d]
run :: Aspects -> Stmt -> Store
run a s = execState (runReaderT (stmt s) a) (fromList [])
run a s = execState (runReaderT (stmt s) a) (Map.fromList [])
aspects1Demo :: IO ()
aspects1Demo = do
aspectPascalDemo :: IO ()
aspectPascalDemo = do
putStrLn "Aspect Weaving -> Monad Transformers"
demo (run [countSets] program)
demo (run [countGets] program)

View File

@ -17,6 +17,8 @@ import Strategy
import TemplateMethod
import Visitor
import MapReduce
import MiniPascal
import AspectPascal
main :: IO ()
main = do
@ -37,3 +39,5 @@ main = do
interpreterDemo
infinityDemo
mapReduceDemo
miniPascalDemo
aspectPascalDemo

View File

@ -1,12 +1,13 @@
{-# LANGUAGE FlexibleContexts #-}
module Aspects where
module MiniPascal where
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Writer
import Data.Map (Map, fromList, assocs)
import qualified Data.Map as Map (lookup, insert)
import Interpreter hiding (eval)
import Data.Map (Map)
import qualified Data.Map as Map (lookup, insert, fromList, assocs)
import Interpreter (Exp (..), Env (..), letExp, fetch)
-- adding a logging capability to the expression evaluator
eval :: Show a => Exp a -> WriterT [String] (Reader (Env a)) a
eval (Var x) = tell ["lookup " ++ x] >> asks (fetch x)
eval (Val i) = tell [show i] >> return i
@ -41,6 +42,8 @@ data Stmt = Skip
| If BExp Stmt Stmt
| While BExp Stmt deriving (Show)
-- an example program: the MiniPascal equivalent of `sum [1..10]`
program :: Stmt
program =
Begin [
"total" := Lit 0,
@ -54,9 +57,6 @@ program =
type Store = Map Id Int
lookup' :: Ord a => Map a b -> a -> Maybe b
lookup' = flip Map.lookup
iexp :: IExp -> State Store Int
iexp (Lit n) = return n
iexp (e1 :+: e2) = liftM2 (+) (iexp e1) (iexp e2)
@ -95,19 +95,19 @@ setVar i x = do
getVar :: MonadState Store m => Id -> m Int
getVar i = do
s <- get
case lookup' s i of
case Map.lookup i s of
Nothing -> return 0
(Just v) -> return v
run :: Stmt -> Store
run s = execState (stmt s) (fromList [])
run s = execState (stmt s) (Map.fromList [])
demo :: Store -> IO ()
demo store = print (assocs store)
demo store = print (Map.assocs store)
aspectsDemo :: IO ()
aspectsDemo = do
miniPascalDemo :: IO ()
miniPascalDemo = do
putStrLn "Aspect Weaving -> Monad Transformers"
let env = [("pi", pi)]
print $ runReader (runWriterT (eval letExp)) env