-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLskTransformationMonad.hs
103 lines (78 loc) · 3.2 KB
/
LskTransformationMonad.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
module LskTransformationMonad where
import LskParseTree
import HsSyn
import RdrName
import SrcLoc
import Outputable
import ErrUtils ( Message )
import MonadUtils
import HscTypes
-------------------------------------------------------------------------------------
--- TransformationMonad
-------------------------------------------------------------------------------------
--- The Transformation Monad is basically a combination of the
--- Error+Reader Monad with an IO Monad
data LskEnvironment = LskEnv
-- SUCCESS CONT. FAILURE CONT.
(forall a.(ParseTree -> (ParseTree -> a) -> (ParseTree -> a) -> a)) -- ExprTable
(forall a.(ParseTree -> (ParseTree -> a) -> (ParseTree -> a) -> a)) -- PatTable
(forall a.(ParseTree -> (ParseTree -> a) -> (ParseTree -> a) -> a)) -- TypeTable
(forall a.(ParseTree -> (ParseTree -> a) -> (ParseTree -> a) -> a)) -- DeclTable
-- Transformation Environment
type LskEnvironmentTransformer = LskEnvironment -> IO LskEnvironment
envExprTable (LskEnv e _ _ _) = e
envPatTable (LskEnv _ p _ _) = p
envTypeTable (LskEnv _ _ t _) = t
envDeclTable (LskEnv _ _ _ d) = d
-- The Monad itself
type Variables = String
data TransformationState = TransformationState {
ts_lskenv :: LskEnvironment,
ts_hsc_env :: HscEnv,
ts_freshvars :: [Variables],
ts_evalctx :: ([LImportDecl RdrName], [LHsDecl RdrName])
}
data TransformationError = TrErr SrcSpan Message
data TransformationMonad a = TM { runTM :: TransformationState -> (IO (Either TransformationError (TransformationState,a))) }
instance Monad TransformationMonad where
m >>= k = TM $ \s -> do
a <- runTM m s
case a of
Left l -> return (Left l)
Right (s',r) -> runTM (k r) s'
return a = TM $ \s -> return (Right (s,a))
instance MonadIO TransformationMonad where
liftIO m = TM $ \s -> do
a <- m
return (Right (s,a))
throwError m = TM $ \_ -> return (Left (TrErr noSrcSpan m))
throwErrorAt s m = TM $ \_ -> return (Left (TrErr s m))
m `catchError` h = TM $ \s -> do
a <- runTM m s
case a of
Left l -> runTM (h l) s
Right (s,r) -> return (Right (s,r))
askVars = TM $ \s -> return (Right (s, ts_freshvars s))
askEnv = TM $ \s -> return (Right (s, ts_lskenv s))
askHscEnv = TM $ \s -> return (Right (s, ts_hsc_env s))
askEvalCtx = TM $ \s -> return (Right (s, ts_evalctx s))
getsTM = TM $ \s -> return (Right (s, s))
setsTM s = TM $ \_ -> return (Right (s, ()))
setEvalCtxImports i = TM $ \s ->
return $ Right (s { ts_evalctx = (i, (snd $ ts_evalctx s)) }, ())
addEvalCtxDecl d = TM $ \s -> do
let oldeval = ts_evalctx s
return $ Right (s { ts_evalctx = (fst oldeval, d:(snd oldeval)) }, ())
genSym :: TransformationMonad ParseTree
genSym = do
TM $ \ts ->
let vars = ts_freshvars ts
in return $ Right (ts { ts_freshvars = (tail vars) },
PSym noSrcSpan (head vars))
newFreshVarStream prefix = map (((toEnum 0:prefix) ++) . show) [1..]
withTrfState s' m = TM $ \s -> (runTM m) s'
askTrfState = TM $ \s -> return (Right (s, s))
withEnvTrf f m = TM $ \s -> (runTM m) (s { ts_lskenv = f (ts_lskenv s) })
lift m = TM $ \s -> do
a <- m
return (Right (s,a))