-
Notifications
You must be signed in to change notification settings - Fork 0
/
LibMain.hs
82 lines (70 loc) · 2.34 KB
/
LibMain.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
{-# LANGUAGE ExistentialQuantification #-}
module LibMain where
import System.IO
import System.FilePath
import System.Posix.Files
import Control.Exception
import Text.Read
import System.IO.Error
import Code
import AbstractMachine
import StateMachine
import Compiler
------------------------------------------------------------------------
data Command = Do Value | Load Code Code Code
deriving (Show, Read)
pipePath :: FilePath
pipePath = "/tmp/freefunc"
libMain :: Code -> IO ()
libMain code0 = do
safeCreateNamedPipe (pipePath <.> "command")
withFile (pipePath <.> "command") ReadWriteMode $ \h -> do
hSetBuffering h LineBuffering
putStrLn "Waiting for commands..."
go h code0 (Int 0)
where
go :: Handle -> Code -> Value -> IO ()
go h code state = do
s <- hGetLine h
let mCmd = readMaybe s
case mCmd of
Nothing -> do
putStrLn ("Invalid command: " ++ s)
go h code state
Just (Load old new migration) -> do
if code /= old
then do
putStrLn "The version running isn't the one the upgrade expects. Aborting upgrade."
go h code state
else do
let (migratedState, _, _, _) = exec (state, migration, Unit, [])
putStrLn "Upgrade successful!"
go h new migratedState
Just (Do input) -> do
let (output, _, state', _) = exec (input, code, state, [])
putStrLn ("Output: " ++ show output)
putStrLn ("New state: " ++ show state')
go h code state'
incr :: IO ()
incr = writeFile (pipePath <.> "command") (show (Do (L Unit)) ++ "\n")
count :: IO ()
count = writeFile (pipePath <.> "command") (show (Do (R Unit)) ++ "\n")
data Upgrade = forall s s' a a' b b'. Upgrade
{ oldSM :: FreeFunc s a b
, newSM :: FreeFunc s' a' b'
, stateMigration :: FreeFunc () s s'
}
upgrade :: Upgrade -> IO ()
upgrade (Upgrade old new migration) = writeFile (pipePath <.> "command")
(show (Load (compile old) (compile new) (compile migration)) ++ "\n")
safeCreateNamedPipe :: FilePath -> IO ()
safeCreateNamedPipe fp =
catchJust
(\e -> if isAlreadyExistsErrorType (ioeGetErrorType e)
then Just ()
else Nothing)
(createNamedPipe fp
(namedPipeMode `unionFileModes`
ownerReadMode `unionFileModes`
ownerWriteMode))
return