184
|
1 |
namespace s = "http://eighty-twenty.org/etng/r1/ns/stream#"; |
|
2 |
namespace n = "http://eighty-twenty.org/etng/r1/ns/number#"; |
|
3 |
namespace repl = "http://eighty-twenty.org/etng/r1/ns/repl#"; |
|
4 |
namespace socket = "http://eighty-twenty.org/etng/r1/ns/socket#"; |
|
5 |
namespace string = "http://eighty-twenty.org/etng/r1/ns/string#"; |
|
6 |
|
|
7 |
define :true = <.:true>; |
|
8 |
define :false = <.:false>; |
|
9 |
|
|
10 |
define :repeat block -> |
|
11 |
do block(); |
|
12 |
:repeat block; |
|
13 |
|
|
14 |
define s:foldl stream seed fn -> |
|
15 |
<(stream, seed)> [ [|], seed = seed; |
|
16 |
[f|r], seed -> self(r, fn(f, seed)) ]; |
|
17 |
|
|
18 |
define s:foldr stream seed fn -> |
|
19 |
<stream> [ [|] = seed; |
|
20 |
[f|r] -> fn(f, self(r)) ]; |
|
21 |
|
|
22 |
define s:reverse stream -> s:foldl stream [|] s:cons; |
|
23 |
define s:append(s1, s2) -> s:foldr s1 s2 s:cons; |
|
24 |
|
|
25 |
define s:foldlK stream seed fn k -> |
|
26 |
<(stream, seed)> [ [|], seed = k seed; |
|
27 |
[f|r], seed -> fn (f, seed) {v -> self(r, v)} ]; |
|
28 |
|
|
29 |
define s:foldrK stream seed fn k -> |
|
30 |
<(stream, k)> [ [|], k = k seed; |
|
31 |
[f|r], k = self(r, {v -> fn (f, v) k}) ]; |
|
32 |
|
|
33 |
define n:range = { |
|
34 |
(low, high, step) -> (low < high) { |
|
35 |
.:true -> [low | n:range(low + step, high, step)]; |
|
36 |
.:false -> [|] |
|
37 |
}; |
|
38 |
(low, high) -> n:range(low, high, 1); |
|
39 |
(high) -> n:range(0, high, 1) |
|
40 |
}; |
|
41 |
|
|
42 |
define s:concatenate stream -> s:foldr stream [|] s:append; |
|
43 |
|
|
44 |
define s:map stream fn -> s:foldr stream [|] {elt, acc -> [fn(elt) | acc]}; |
|
45 |
|
|
46 |
define s:foreach stream fn -> |
|
47 |
<stream> [ [|] -> .:ok; |
|
48 |
[f|r] -> do fn(f); self(r) ]; |
|
49 |
|
|
50 |
define string:stream = { |
|
51 |
(str, startIndex) -> |
|
52 |
let len = string:length(str); |
|
53 |
<startIndex> [ index -> |
|
54 |
(index < len) { |
|
55 |
.:true -> {.bytes = str; |
|
56 |
.offset = index; |
|
57 |
visitor -> visitor.s:next(string:charAt(str, index), |
|
58 |
self(index + 1))}; |
|
59 |
.:false -> s:nil |
|
60 |
} |
|
61 |
]; |
|
62 |
|
|
63 |
(str) -> string:stream(str, 0) |
|
64 |
}; |
|
65 |
|
|
66 |
define repl:newOn(port) -> |
|
67 |
let socket = socket:ServerSocket.new(port); |
|
68 |
:spawn { repl:acceptLoop(socket) }; |
|
69 |
|
|
70 |
define repl:acceptLoop(serverSocket) -> |
|
71 |
:repeat { |
|
72 |
let sock = serverSocket.accept(); |
|
73 |
:spawn { repl:mainLoop(sock) } |
|
74 |
}; |
|
75 |
|
|
76 |
define repl:mainLoop(sock) -> |
|
77 |
catch { sessionReturn -> |
|
78 |
let writer = sock.writer(); |
|
79 |
do writer.println("Welcome to ThiNG!"); |
|
80 |
:repeat { |
|
81 |
do writer.print("ThiNG> "); |
|
82 |
do sock.compileOneStatement() { |
|
83 |
.ok(thunk) -> writer.println(thunk()); |
|
84 |
.error(detail) -> |
|
85 |
do s:foreach ["PARSE ERROR", detail] (writer.println); |
|
86 |
do sock.close(); |
|
87 |
sessionReturn(); |
|
88 |
}; |
|
89 |
writer.println(); |
|
90 |
} |
|
91 |
}; |