-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathRuntime.hs
59 lines (50 loc) · 1.66 KB
/
Runtime.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
module Runtime ( getString
, PHPRuntime
, RuntimeEnv (..)
, runRuntime
, output
, setVar
, getVar
, forLoop
, module Tokenizer
, module Conversion
) where
import Tokenizer
import Conversion
import Control.Monad.Trans.Class
import Control.Monad.Reader
import Data.IORef
import Data.Maybe
type PHPRuntime = ReaderT RuntimeEnv IO
data RuntimeEnv = RuntimeEnv { locals :: IORef [(String, IORef PHPValue)] }
runRuntime :: RuntimeEnv -> (PHPRuntime a) -> IO ()
runRuntime env r = void $ liftIO $ runReaderT r env
getVar :: String -> PHPRuntime PHPValue
getVar name = do
vars <- liftM locals ask >>= liftIO . readIORef
maybe (return PHPNull) (liftIO . readIORef) (lookup name vars)
setVar :: String -> PHPValue -> PHPRuntime PHPValue
setVar name value = do
localsRef <- liftM locals ask
locals <- liftIO $ readIORef localsRef
case lookup name locals of
Nothing -> liftIO $ do
valRef <- newIORef value
writeIORef localsRef ((name, valRef) : locals)
return value
Just ref -> liftIO $ do
writeIORef ref value
return value
getString :: PHPValue -> String
getString (PHPString s) = s
getString v = getString $ castToString v
output :: String -> PHPRuntime ()
output s = liftIO $ putStr s
forLoop :: PHPRuntime () -> PHPRuntime Bool -> PHPRuntime () -> PHPRuntime () -> PHPRuntime ()
forLoop init cond iter expr = init >> forMain
where
forMain = do
condTrue <- cond
when condTrue expr
iter
when condTrue forMain