fs.bend
cswap-bend-cli@0.1.0.0 · 173 lines · 27 definitions
1import Base
2
3
4
5
6
7
8def Res(-A: Type) -> Type:
9 Result<&1, &1, U32 & String, A>
10
11def proc.timeout() -> U32:
12 10000
13
14def proc.max() -> U32:
15 1048576
16
17def tool.status(ok: Bool, status: U32, out: String, err: String) -> Res(String):
18 match ok:
19 case True{}:
20 Done{out}
21 case False{}:
22 Fail{(status, err)}
23
24
25def tool.out(r: Result<&1, &1, U32 & String, U32 & (String & String)>) -> Res(String):
26 match r:
27 case Fail{e}:
28 Fail{e}
29 case Done{(+status, (out, err))}:
30 tool.status(U32.is_eq(status, 0), status, out, err)
31
32def tool.unit(r: Res(String)) -> Res(Unit):
33 match r:
34 case Fail{e}:
35 Fail{e}
36 case Done{out}:
37 Done{Unit{}}
38
39def tool(program: String, args: List<String>) -> IO(Res(String)):
40 IO.bind(Result<&1, &1, U32 & String, U32 & (String & String)>, Res(String),
41 Process.run(program, args, "", proc.max(), proc.timeout()),
42 r => IO.pure(Res(String), tool.out(r)))
43
44def tool_unit(program: String, args: List<String>) -> IO(Res(Unit)):
45 IO.bind(Res(String), Res(Unit), tool(program, args), r => IO.pure(Res(Unit), tool.unit(r)))
46
47
48def then(r: Res(Unit), next: IO(Res(Unit))) -> IO(Res(Unit)):
49 match r:
50 case Fail{e}:
51 IO.pure(Res(Unit), Fail{e})
52 case Done{u}:
53 next
54
55
56
57def read.done(fr: File & Res(String)) -> IO(Res(String)):
58 (f, r) = fr
59 IO.bind(Unit, Res(String), File.close(f), u => IO.pure(Res(String), r))
60
61def read.sized2(f: File, r: Res(U32)) -> IO(Res(String)):
62 match r:
63 case Fail{e}:
64 IO.bind(Unit, Res(String), File.close(f), u => IO.pure(Res(String), Fail{e}))
65 case Done{n}:
66 IO.bind(File & Res(String), Res(String), File.read(f, n), read.done)
67
68def read.sized(fr: File & Res(U32)) -> IO(Res(String)):
69 (f, r) = fr
70 read.sized2(f, r)
71
72def read.open(r: Res(File)) -> IO(Res(String)):
73 match r:
74 case Fail{e}:
75 IO.pure(Res(String), Fail{e})
76 case Done{f}:
77 IO.bind(File & Res(U32), Res(String), File.size(f), read.sized)
78
79
80def read_file(path: String) -> IO(Res(String)):
81 IO.bind(Res(File), Res(String), File.open(path, "r"), read.open)
82
83
84
85def exists.of(r: Result<&1, &1, U32 & String, U32 & (String & String)>) -> Bool:
86 match r:
87 case Fail{e}:
88 False{}
89 case Done{(+status, rest)}:
90 U32.is_eq(status, 0)
91
92
93def exists(path: String) -> IO(Bool):
94 IO.bind(Result<&1, &1, U32 & String, U32 & (String & String)>, Bool,
95 Process.run("/bin/test", ["-e", path], "", proc.max(), proc.timeout()),
96 r => IO.pure(Bool, exists.of(r)))
97
98def names.keep(empty: Bool, h: String, rest: List<&2, String>) -> List<&2, String>:
99 match empty:
100 case True{}:
101 rest
102 case False{}:
103 h <> rest
104
105def names(ls: List<&2, String>) -> List<&2, String>:
106 match ls:
107 case Nil{}:
108 []
109 case Con{+h, t}:
110 names.keep(String.is_empty(h), h, names(t))
111
112def list.of(r: Res(String)) -> Res(List<&2, String>):
113 match r:
114 case Fail{e}:
115 Fail{e}
116 case Done{out}:
117 Done{names(String.lines(out))}
118
119
120
121def list_dir(path: String) -> IO(Res(List<&2, String>)):
122 IO.bind(Res(String), Res(List<&2, String>), tool("/bin/ls", ["-1A", "--", path]),
123 r => IO.pure(Res(List<&2, String>), list.of(r)))
124
125
126
127def sel.s(c: Bool, x: String, y: String) -> String:
128 match c:
129 case True{}:
130 x
131 case False{}:
132 y
133
134def slash.pick(hit: Bool, t: String, rest: String) -> String:
135 match hit:
136 case True{}:
137 t
138 case False{}:
139 rest
140
141
142def slash.drop(s: String) -> String:
143 match s:
144 case SNil{}:
145 SNil{}
146 case SCon{+c, +t}:
147 slash.pick(Char.is_eq(c, '/'), t, slash.drop(t))
148
149def dirname.fin(s: String, absolute: Bool) -> String:
150 match s:
151 case SNil{}:
152 sel.s(absolute, "/", ".")
153 case _:
154 s
155
156
157def dirname(+p: String) -> String:
158 dirname.fin(String.reverse(slash.drop(String.reverse(p))), String.starts_with(p, "/"))
159
160
161
162
163def read.stdin(r: Res(File)) -> IO(Res(String)):
164 match r:
165 case Fail{e}:
166 IO.pure(Res(String), Fail{e})
167 case Done{f}:
168 IO.bind(File & Res(String), Res(String), File.read(f, 1048576), read.done)
169
170
171
172def read_stdin() -> IO(Res(String)):
173 IO.bind(Res(File), Res(String), File.open("/dev/stdin", "r"), read.stdin)