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
|
module test_reload
import StdBool
import StdClass
import StdFile
import StdFunc
import StdInt
import StdString
import Data.Either
import Data.Maybe
import Inotify
/** test_reload
*
* This module will watch the directory it is in. Whenever the attributes of
* its own binaries change, it will exit. Hence, putting it in a loop:
*
* while :; do ./test_reload; done
*
* will give a program that automatically reloads itself when its binary has
* changed.
*
* Test it by running `make run_test_reload`, then editing `changeme` below and
* running `make test_reload` to recompile.
* You can also use `touch test_reload`.
*/
my_name :== "test_reload"
my_dir :== "."
changeme :== 42
verbose :== False
:: Void = Void
Start w
# (io,w) = stdio w
# io = io <<< changeme <<< " (edit changeme and recompile)\n"
# (ok,w) = fclose io w
# (Just inot) = inotify_init Void
# (Right watch,inot) = inotify_add_watch reload IN_ATTRIB my_dir inot
# (inot,w) = inotify_loop_forever inot w
= inotify_close inot
where
reload :: !INEvent (Maybe String) Void !*World -> *(Void, *World)
reload ev mbName _ w
# w = echo (\f -> f <<< "event: " <<< ev <<< "; " <<< mbName) w
| isNothing mbName = (Void, w)
# (Just name) = mbName
| inotify_is_event IN_ATTRIB ev && name == my_name
# w = echo (\f -> f <<< "reloading...") w
# w = exit 127 w
= (Void, w)
= (Void, w)
echo :: (*File -> *File) *World -> *World
echo f w
# (io,w) = stdio w
# io = if verbose (flip (<<<) "\n" o f) id io
# (ok,w) = fclose io w
= w
exit :: !Int !*World -> *World
exit c w = code {
ccall exit "I:V:A"
}
instance <<< (Maybe x) | <<< x
where
(<<<) f Nothing = f
(<<<) f (Just x) = f <<< x
|