@shd101wyy/yo 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/skills/yo-async-effects/SKILL.md +4 -4
- package/.github/skills/yo-async-effects/async-effects-recipes.md +40 -40
- package/.github/skills/yo-core-patterns/SKILL.md +1 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +30 -26
- package/.github/skills/yo-project-workflow/SKILL.md +6 -3
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
- package/.github/skills/yo-syntax/SKILL.md +7 -6
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +78 -60
- package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
- package/README.md +10 -8
- package/out/cjs/index.cjs +583 -567
- package/out/cjs/yo-cli.cjs +664 -632
- package/out/cjs/yo-lsp.cjs +510 -485
- package/out/esm/index.mjs +538 -522
- package/out/types/src/codegen/codegen-c.d.ts +2 -2
- package/out/types/src/codegen/functions/collection.d.ts +2 -2
- package/out/types/src/codegen/functions/context.d.ts +3 -2
- package/out/types/src/codegen/types/collection.d.ts +2 -2
- package/out/types/src/codegen/utils/index.d.ts +3 -1
- package/out/types/src/doc/builder.d.ts +2 -2
- package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
- package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
- package/out/types/src/evaluator/context.d.ts +8 -9
- package/out/types/src/evaluator/index.d.ts +3 -3
- package/out/types/src/evaluator/types/record.d.ts +14 -0
- package/out/types/src/evaluator/types/validation.d.ts +2 -2
- package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
- package/out/types/src/evaluator/values/impl.d.ts +1 -1
- package/out/types/src/expr.d.ts +1 -4
- package/out/types/src/formatter.d.ts +11 -0
- package/out/types/src/function-value.d.ts +1 -1
- package/out/types/src/lsp/document-manager.d.ts +1 -1
- package/out/types/src/lsp/formatting.d.ts +2 -0
- package/out/types/src/module-manager.d.ts +3 -3
- package/out/types/src/tests/formatter.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +3 -4
- package/out/types/src/types/definitions.d.ts +8 -19
- package/out/types/src/types/guards.d.ts +3 -3
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/types/utils.d.ts +1 -1
- package/out/types/src/value-tag.d.ts +0 -1
- package/out/types/src/value.d.ts +6 -13
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/alg/hash.yo +13 -21
- package/std/allocator.yo +25 -40
- package/std/async.yo +3 -7
- package/std/build.yo +105 -151
- package/std/cli/arg_parser.yo +184 -169
- package/std/collections/array_list.yo +350 -314
- package/std/collections/btree_map.yo +142 -131
- package/std/collections/deque.yo +132 -128
- package/std/collections/hash_map.yo +542 -566
- package/std/collections/hash_set.yo +623 -687
- package/std/collections/linked_list.yo +275 -293
- package/std/collections/ordered_map.yo +113 -85
- package/std/collections/priority_queue.yo +73 -73
- package/std/crypto/md5.yo +191 -95
- package/std/crypto/random.yo +56 -64
- package/std/crypto/sha256.yo +151 -107
- package/std/encoding/base64.yo +87 -81
- package/std/encoding/hex.yo +43 -50
- package/std/encoding/html.yo +56 -81
- package/std/encoding/html_char_utils.yo +7 -13
- package/std/encoding/html_entities.yo +2248 -2253
- package/std/encoding/json.yo +316 -224
- package/std/encoding/punycode.yo +86 -116
- package/std/encoding/toml.yo +67 -66
- package/std/encoding/utf16.yo +37 -44
- package/std/env.yo +62 -91
- package/std/error.yo +12 -20
- package/std/fmt/display.yo +5 -9
- package/std/fmt/index.yo +8 -14
- package/std/fmt/to_string.yo +330 -315
- package/std/fmt/writer.yo +58 -87
- package/std/fs/dir.yo +83 -102
- package/std/fs/file.yo +147 -180
- package/std/fs/metadata.yo +45 -78
- package/std/fs/temp.yo +55 -65
- package/std/fs/types.yo +27 -40
- package/std/fs/walker.yo +53 -68
- package/std/gc.yo +5 -8
- package/std/glob.yo +30 -43
- package/std/http/client.yo +107 -120
- package/std/http/http.yo +106 -96
- package/std/http/index.yo +4 -6
- package/std/imm/list.yo +88 -93
- package/std/imm/map.yo +528 -464
- package/std/imm/set.yo +52 -57
- package/std/imm/sorted_map.yo +340 -286
- package/std/imm/sorted_set.yo +57 -63
- package/std/imm/string.yo +404 -345
- package/std/imm/vec.yo +173 -181
- package/std/io/reader.yo +3 -6
- package/std/io/writer.yo +4 -8
- package/std/libc/assert.yo +5 -9
- package/std/libc/ctype.yo +32 -22
- package/std/libc/dirent.yo +26 -25
- package/std/libc/errno.yo +164 -90
- package/std/libc/fcntl.yo +52 -45
- package/std/libc/float.yo +66 -44
- package/std/libc/limits.yo +42 -33
- package/std/libc/math.yo +53 -82
- package/std/libc/signal.yo +72 -47
- package/std/libc/stdatomic.yo +217 -188
- package/std/libc/stdint.yo +5 -29
- package/std/libc/stdio.yo +5 -29
- package/std/libc/stdlib.yo +32 -39
- package/std/libc/string.yo +5 -23
- package/std/libc/sys/stat.yo +58 -56
- package/std/libc/time.yo +5 -19
- package/std/libc/unistd.yo +5 -20
- package/std/libc/wctype.yo +6 -9
- package/std/libc/windows.yo +26 -30
- package/std/log.yo +41 -55
- package/std/net/addr.yo +102 -97
- package/std/net/dns.yo +27 -28
- package/std/net/errors.yo +50 -49
- package/std/net/tcp.yo +113 -124
- package/std/net/udp.yo +55 -66
- package/std/os/env.yo +35 -33
- package/std/os/signal.yo +15 -25
- package/std/path.yo +276 -311
- package/std/prelude.yo +6316 -4333
- package/std/process/command.yo +87 -103
- package/std/process/index.yo +12 -31
- package/std/regex/compiler.yo +196 -95
- package/std/regex/flags.yo +58 -39
- package/std/regex/index.yo +157 -173
- package/std/regex/match.yo +20 -31
- package/std/regex/node.yo +134 -152
- package/std/regex/parser.yo +283 -259
- package/std/regex/unicode.yo +172 -202
- package/std/regex/vm.yo +155 -171
- package/std/string/index.yo +5 -7
- package/std/string/rune.yo +45 -55
- package/std/string/string.yo +937 -964
- package/std/string/string_builder.yo +94 -104
- package/std/string/unicode.yo +46 -64
- package/std/sync/channel.yo +72 -73
- package/std/sync/cond.yo +31 -36
- package/std/sync/mutex.yo +30 -32
- package/std/sync/once.yo +13 -16
- package/std/sync/rwlock.yo +26 -31
- package/std/sync/waitgroup.yo +20 -25
- package/std/sys/advise.yo +16 -24
- package/std/sys/bufio/buf_reader.yo +77 -93
- package/std/sys/bufio/buf_writer.yo +52 -65
- package/std/sys/clock.yo +4 -9
- package/std/sys/constants.yo +77 -61
- package/std/sys/copy.yo +4 -10
- package/std/sys/dir.yo +26 -43
- package/std/sys/dns.yo +41 -61
- package/std/sys/errors.yo +95 -103
- package/std/sys/events.yo +45 -57
- package/std/sys/externs.yo +319 -267
- package/std/sys/fallocate.yo +7 -11
- package/std/sys/fcntl.yo +14 -22
- package/std/sys/file.yo +26 -40
- package/std/sys/future.yo +5 -8
- package/std/sys/iov.yo +12 -25
- package/std/sys/lock.yo +12 -13
- package/std/sys/mmap.yo +38 -43
- package/std/sys/path.yo +3 -8
- package/std/sys/perm.yo +7 -21
- package/std/sys/pipe.yo +5 -12
- package/std/sys/process.yo +23 -29
- package/std/sys/seek.yo +10 -12
- package/std/sys/signal.yo +7 -13
- package/std/sys/signals.yo +52 -35
- package/std/sys/socket.yo +63 -58
- package/std/sys/socketpair.yo +3 -6
- package/std/sys/sockinfo.yo +11 -20
- package/std/sys/statfs.yo +11 -34
- package/std/sys/statx.yo +25 -52
- package/std/sys/sysinfo.yo +15 -20
- package/std/sys/tcp.yo +62 -92
- package/std/sys/temp.yo +5 -9
- package/std/sys/time.yo +5 -15
- package/std/sys/timer.yo +6 -11
- package/std/sys/tty.yo +10 -18
- package/std/sys/udp.yo +22 -39
- package/std/sys/umask.yo +3 -6
- package/std/sys/unix.yo +33 -52
- package/std/testing/bench.yo +49 -52
- package/std/thread.yo +10 -15
- package/std/time/datetime.yo +105 -89
- package/std/time/duration.yo +43 -56
- package/std/time/instant.yo +13 -18
- package/std/time/sleep.yo +5 -9
- package/std/url/index.yo +184 -209
- package/std/worker.yo +6 -10
- package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
- package/out/types/src/evaluator/types/module.d.ts +0 -19
package/std/http/http.yo
CHANGED
|
@@ -1,163 +1,177 @@
|
|
|
1
1
|
//! HTTP core types — methods, headers, requests, and responses.
|
|
2
2
|
// std/http/http.yo - HTTP types and request/response builders
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
{
|
|
6
|
-
{ ToString } :: import "../fmt";
|
|
7
|
-
|
|
3
|
+
open(import("../string"));
|
|
4
|
+
{ ArrayList } :: import("../collections/array_list");
|
|
5
|
+
{ ToString } :: import("../fmt");
|
|
8
6
|
/// Standard HTTP request methods.
|
|
9
7
|
HttpMethod :: enum(GET, POST, PUT, DELETE, HEAD, PATCH);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
impl(
|
|
9
|
+
HttpMethod,
|
|
10
|
+
ToString(
|
|
11
|
+
to_string : (
|
|
12
|
+
self ->
|
|
13
|
+
match(
|
|
14
|
+
self,
|
|
15
|
+
.GET => `GET`,
|
|
16
|
+
.POST => `POST`,
|
|
17
|
+
.PUT => `PUT`,
|
|
18
|
+
.DELETE => `DELETE`,
|
|
19
|
+
.HEAD => `HEAD`,
|
|
20
|
+
.PATCH => `PATCH`
|
|
21
|
+
)
|
|
20
22
|
)
|
|
21
23
|
)
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
+
);
|
|
24
25
|
/// An HTTP header as a name-value pair.
|
|
25
|
-
HttpHeader :: object(name: String, value: String);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
HttpHeader :: object(name : String, value : String);
|
|
27
|
+
impl(
|
|
28
|
+
HttpHeader,
|
|
28
29
|
/// Create a new header with the given name and value.
|
|
29
|
-
new : (fn(name: String, value: String) -> Self)(
|
|
30
|
-
Self(name: name, value: value)
|
|
30
|
+
new : (fn(name : String, value : String) -> Self)(
|
|
31
|
+
Self(name : name, value : value)
|
|
31
32
|
)
|
|
32
33
|
);
|
|
33
|
-
|
|
34
34
|
/// An HTTP request with method, path, headers, and optional body.
|
|
35
35
|
HttpRequest :: object(
|
|
36
|
-
method: HttpMethod,
|
|
37
|
-
path: String,
|
|
38
|
-
headers: ArrayList(HttpHeader),
|
|
39
|
-
body: String
|
|
36
|
+
method : HttpMethod,
|
|
37
|
+
path : String,
|
|
38
|
+
headers : ArrayList(HttpHeader),
|
|
39
|
+
body : String
|
|
40
40
|
);
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
impl(
|
|
42
|
+
HttpRequest,
|
|
43
43
|
/// Create a new request with the given method and path.
|
|
44
|
-
new : (fn(method: HttpMethod, path: String) -> Self)(
|
|
45
|
-
Self(method: method, path: path, headers: ArrayList(HttpHeader).new(), body: ``)
|
|
44
|
+
new : (fn(method : HttpMethod, path : String) -> Self)(
|
|
45
|
+
Self(method : method, path : path, headers : ArrayList(HttpHeader).new(), body : ``)
|
|
46
46
|
),
|
|
47
|
-
|
|
48
47
|
/// Add a header and return the request (builder pattern).
|
|
49
|
-
header : (fn(self: Self, name: String, value: String) -> Self)({
|
|
48
|
+
header : (fn(self : Self, name : String, value : String) -> Self)({
|
|
50
49
|
self.headers.push(HttpHeader.new(name, value));
|
|
51
50
|
self
|
|
52
51
|
}),
|
|
53
|
-
|
|
54
52
|
/// Set the request body and return the request (builder pattern).
|
|
55
|
-
with_body : (fn(self: Self, body: String) -> Self)({
|
|
53
|
+
with_body : (fn(self : Self, body : String) -> Self)({
|
|
56
54
|
self.body = body;
|
|
57
55
|
self
|
|
58
56
|
}),
|
|
59
|
-
|
|
60
57
|
/// Set the Host header.
|
|
61
|
-
set_host : (fn(self: Self, host: String) -> unit)({
|
|
58
|
+
set_host : (fn(self : Self, host : String) -> unit)({
|
|
62
59
|
self.headers.push(HttpHeader.new(`Host`, host));
|
|
63
60
|
}),
|
|
64
|
-
|
|
65
61
|
/// Append a header to the request.
|
|
66
|
-
set_header : (fn(self: Self, name: String, value: String) -> unit)({
|
|
62
|
+
set_header : (fn(self : Self, name : String, value : String) -> unit)({
|
|
67
63
|
self.headers.push(HttpHeader.new(name, value));
|
|
68
64
|
}),
|
|
69
|
-
|
|
70
65
|
/// Set the request body.
|
|
71
|
-
set_body : (fn(self: Self, body: String) -> unit)({
|
|
66
|
+
set_body : (fn(self : Self, body : String) -> unit)({
|
|
72
67
|
self.body = body;
|
|
73
68
|
}),
|
|
74
|
-
|
|
75
69
|
/// Serialize the request to an HTTP/1.1 wire-format string.
|
|
76
|
-
to_string : (fn(self: Self) -> String)({
|
|
70
|
+
to_string : (fn(self : Self) -> String)({
|
|
77
71
|
result := `${self.method.to_string()} ${self.path} HTTP/1.1\r\n`;
|
|
78
72
|
i := usize(0);
|
|
79
|
-
while
|
|
73
|
+
while(i < self.headers.len(), i = (i + usize(1)), {
|
|
80
74
|
h := self.headers.get(i).unwrap();
|
|
81
75
|
result = `${result}${h.name}: ${h.value}\r\n`;
|
|
82
|
-
};
|
|
76
|
+
});
|
|
83
77
|
result = `${result}\r\n`;
|
|
84
78
|
cond(
|
|
85
|
-
(!(self.body.is_empty())) => {
|
|
79
|
+
(!(self.body.is_empty())) => {
|
|
80
|
+
result = `${result}${self.body}`;
|
|
81
|
+
},
|
|
86
82
|
true => ()
|
|
87
83
|
);
|
|
88
84
|
result
|
|
89
85
|
})
|
|
90
86
|
);
|
|
91
|
-
|
|
92
87
|
/// An HTTP response with status code, headers, and body.
|
|
93
88
|
HttpResponse :: object(
|
|
94
|
-
status_code: i32,
|
|
95
|
-
status_text: String,
|
|
96
|
-
headers: ArrayList(HttpHeader),
|
|
97
|
-
body: String
|
|
89
|
+
status_code : i32,
|
|
90
|
+
status_text : String,
|
|
91
|
+
headers : ArrayList(HttpHeader),
|
|
92
|
+
body : String
|
|
98
93
|
);
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
impl(
|
|
95
|
+
HttpResponse,
|
|
101
96
|
/// Create a new response with the given status code and text.
|
|
102
|
-
new : (fn(status_code: i32, status_text: String) -> Self)(
|
|
103
|
-
Self(status_code: status_code, status_text: status_text, headers: ArrayList(HttpHeader).new(), body: ``)
|
|
97
|
+
new : (fn(status_code : i32, status_text : String) -> Self)(
|
|
98
|
+
Self(status_code : status_code, status_text : status_text, headers : ArrayList(HttpHeader).new(), body : ``)
|
|
104
99
|
),
|
|
105
|
-
|
|
106
100
|
/// Look up a header value by name (case-insensitive).
|
|
107
|
-
get_header : (fn(self: Self, name: String) -> Option(String))({
|
|
101
|
+
get_header : (fn(self : Self, name : String) -> Option(String))({
|
|
108
102
|
lower_name := name.to_lowercase();
|
|
109
103
|
i := usize(0);
|
|
110
|
-
while
|
|
104
|
+
while(i < self.headers.len(), i = (i + usize(1)), {
|
|
111
105
|
h := self.headers.get(i).unwrap();
|
|
112
|
-
cond(
|
|
113
|
-
|
|
106
|
+
cond(
|
|
107
|
+
(h.name.to_lowercase() == lower_name) => {
|
|
108
|
+
return(.Some(h.value));
|
|
109
|
+
},
|
|
110
|
+
true => ()
|
|
111
|
+
);
|
|
112
|
+
});
|
|
114
113
|
.None
|
|
115
114
|
}),
|
|
116
|
-
|
|
117
115
|
/// Return `true` if the status code is in the 2xx range.
|
|
118
|
-
is_ok : (fn(self: Self) -> bool)(
|
|
119
|
-
(
|
|
116
|
+
is_ok : (fn(self : Self) -> bool)(
|
|
117
|
+
(self.status_code >= i32(200)) && (self.status_code < i32(300))
|
|
120
118
|
),
|
|
121
|
-
|
|
122
119
|
/// Return `true` if the status code is in the 3xx range.
|
|
123
|
-
is_redirect : (fn(self: Self) -> bool)(
|
|
124
|
-
(
|
|
120
|
+
is_redirect : (fn(self : Self) -> bool)(
|
|
121
|
+
(self.status_code >= i32(300)) && (self.status_code < i32(400))
|
|
125
122
|
),
|
|
126
|
-
|
|
127
123
|
/// Return `true` if the status code is 4xx or higher.
|
|
128
|
-
is_error : (fn(self: Self) -> bool)(
|
|
129
|
-
|
|
124
|
+
is_error : (fn(self : Self) -> bool)(
|
|
125
|
+
self.status_code >= i32(400)
|
|
130
126
|
)
|
|
131
127
|
);
|
|
132
|
-
|
|
133
128
|
/// Parse a raw HTTP response string into an `HttpResponse`.
|
|
134
|
-
parse_response :: (fn(raw: String) -> Result(HttpResponse, String))({
|
|
129
|
+
parse_response :: (fn(raw : String) -> Result(HttpResponse, String))({
|
|
135
130
|
lines := raw.split(`\r\n`);
|
|
136
|
-
cond(
|
|
137
|
-
|
|
131
|
+
cond(
|
|
132
|
+
(lines.len() == usize(0)) => {
|
|
133
|
+
return(.Err(`Empty response`));
|
|
134
|
+
},
|
|
135
|
+
true => ()
|
|
136
|
+
);
|
|
138
137
|
status_line := lines.get(usize(0)).unwrap();
|
|
139
|
-
cond(
|
|
140
|
-
|
|
138
|
+
cond(
|
|
139
|
+
(!(status_line.starts_with(`HTTP/`))) => {
|
|
140
|
+
return(.Err(`Invalid status line`));
|
|
141
|
+
},
|
|
142
|
+
true => ()
|
|
143
|
+
);
|
|
141
144
|
sp1_opt := status_line.index_of(` `);
|
|
142
|
-
cond(
|
|
145
|
+
cond(
|
|
146
|
+
sp1_opt.is_none() => {
|
|
147
|
+
return(.Err(`Invalid status line format`));
|
|
148
|
+
},
|
|
149
|
+
true => ()
|
|
150
|
+
);
|
|
143
151
|
sp1 := sp1_opt.unwrap();
|
|
144
|
-
rest := status_line.substring(
|
|
145
|
-
|
|
152
|
+
rest := status_line.substring(sp1 + usize(1), status_line.len());
|
|
146
153
|
sp2_opt := rest.index_of(` `);
|
|
147
|
-
cond(
|
|
154
|
+
cond(
|
|
155
|
+
sp2_opt.is_none() => {
|
|
156
|
+
return(.Err(`Invalid status line format`));
|
|
157
|
+
},
|
|
158
|
+
true => ()
|
|
159
|
+
);
|
|
148
160
|
sp2 := sp2_opt.unwrap();
|
|
149
161
|
code_str := rest.substring(usize(0), sp2);
|
|
150
|
-
status_text := rest.substring(
|
|
151
|
-
|
|
162
|
+
status_text := rest.substring(sp2 + usize(1), rest.len());
|
|
152
163
|
code_opt := code_str.parse_i32();
|
|
153
|
-
cond(
|
|
164
|
+
cond(
|
|
165
|
+
code_opt.is_none() => {
|
|
166
|
+
return(.Err(`Invalid status code`));
|
|
167
|
+
},
|
|
168
|
+
true => ()
|
|
169
|
+
);
|
|
154
170
|
code := code_opt.unwrap();
|
|
155
|
-
|
|
156
171
|
resp := HttpResponse.new(code, status_text);
|
|
157
|
-
|
|
158
172
|
j := usize(1);
|
|
159
173
|
body_start := lines.len();
|
|
160
|
-
while
|
|
174
|
+
while(j < lines.len(), j = (j + usize(1)), {
|
|
161
175
|
hline := lines.get(j).unwrap();
|
|
162
176
|
cond(
|
|
163
177
|
hline.is_empty() => {
|
|
@@ -170,31 +184,28 @@ parse_response :: (fn(raw: String) -> Result(HttpResponse, String))({
|
|
|
170
184
|
colon_opt.is_some() => {
|
|
171
185
|
colon := colon_opt.unwrap();
|
|
172
186
|
hname := hline.substring(usize(0), colon).trim();
|
|
173
|
-
hval := hline.substring(
|
|
187
|
+
hval := hline.substring(colon + usize(1), hline.len()).trim();
|
|
174
188
|
resp.headers.push(HttpHeader.new(hname, hval));
|
|
175
189
|
},
|
|
176
190
|
true => ()
|
|
177
191
|
);
|
|
178
192
|
}
|
|
179
193
|
);
|
|
180
|
-
};
|
|
181
|
-
|
|
194
|
+
});
|
|
182
195
|
cond(
|
|
183
196
|
(body_start < lines.len()) => {
|
|
184
197
|
resp.body = lines.get(body_start).unwrap();
|
|
185
198
|
m := (body_start + usize(1));
|
|
186
|
-
while
|
|
199
|
+
while(m < lines.len(), m = (m + usize(1)), {
|
|
187
200
|
resp.body = `${resp.body}\r\n${lines.get(m).unwrap()}`;
|
|
188
|
-
};
|
|
201
|
+
});
|
|
189
202
|
},
|
|
190
203
|
true => ()
|
|
191
204
|
);
|
|
192
|
-
|
|
193
205
|
.Ok(resp)
|
|
194
206
|
});
|
|
195
|
-
|
|
196
207
|
/// Return the standard status text for an HTTP status code.
|
|
197
|
-
http_status_text :: (fn(code: i32) -> String)(
|
|
208
|
+
http_status_text :: (fn(code : i32) -> String)(
|
|
198
209
|
cond(
|
|
199
210
|
(code == i32(200)) => `OK`,
|
|
200
211
|
(code == i32(201)) => `Created`,
|
|
@@ -211,6 +222,5 @@ http_status_text :: (fn(code: i32) -> String)(
|
|
|
211
222
|
true => `Unknown`
|
|
212
223
|
)
|
|
213
224
|
);
|
|
214
|
-
|
|
215
|
-
export
|
|
216
|
-
export parse_response, http_status_text;
|
|
225
|
+
export(HttpMethod, HttpHeader, HttpRequest, HttpResponse);
|
|
226
|
+
export(parse_response, http_status_text);
|
package/std/http/index.yo
CHANGED
|
@@ -13,11 +13,9 @@
|
|
|
13
13
|
// resp := io.await(fetch(`http://example.com`, using(io)));
|
|
14
14
|
// println(resp.body);
|
|
15
15
|
// });
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export
|
|
16
|
+
_http :: import("./http.yo");
|
|
17
|
+
_client :: import("./client.yo");
|
|
18
|
+
export(
|
|
21
19
|
...(_http),
|
|
22
20
|
...(_client)
|
|
23
|
-
;
|
|
21
|
+
);
|
package/std/imm/list.yo
CHANGED
|
@@ -15,24 +15,22 @@
|
|
|
15
15
|
//! assert((xs.head().unwrap() == i32(1)), "head is 1");
|
|
16
16
|
//! assert((xs.len() == usize(3)), "length is 3");
|
|
17
17
|
//! ```
|
|
18
|
-
|
|
19
|
-
{ GlobalAllocator } :: import "../allocator.yo";
|
|
18
|
+
{ GlobalAllocator } :: import("../allocator.yo");
|
|
20
19
|
{ malloc, free } :: GlobalAllocator;
|
|
21
|
-
{ memcpy } :: import
|
|
22
|
-
|
|
20
|
+
{ memcpy } :: import("../libc/string.yo");
|
|
23
21
|
/// Internal cons cell — atomic object for thread-safe structural sharing.
|
|
24
22
|
ListNode :: (fn(comptime(T) : Type, where(T <: Send)) -> comptime(Type))(
|
|
25
|
-
atomic
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
atomic(
|
|
24
|
+
object(
|
|
25
|
+
_value : T,
|
|
26
|
+
_next : Option(Self)
|
|
27
|
+
)
|
|
28
28
|
)
|
|
29
29
|
);
|
|
30
|
-
|
|
31
30
|
// Manual Acyclic impl — ListNode is self-referential, so auto-derivation skips it.
|
|
32
31
|
// This is safe because ListNode is immutable: all operations create new nodes and never
|
|
33
32
|
// mutate existing ones, making it impossible to form cycles at runtime.
|
|
34
33
|
impl(forall(T : Type), where(T <: Send), ListNode(T), Acyclic());
|
|
35
|
-
|
|
36
34
|
/// Persistent immutable singly-linked list.
|
|
37
35
|
///
|
|
38
36
|
/// A value-type wrapper around an optional chain of `ListNode` atomic objects.
|
|
@@ -44,211 +42,208 @@ List :: (fn(comptime(T) : Type, where(T <: Send)) -> comptime(Type))(
|
|
|
44
42
|
_len : usize
|
|
45
43
|
)
|
|
46
44
|
);
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
impl(
|
|
46
|
+
forall(T : Type),
|
|
47
|
+
where(T <: Send),
|
|
48
|
+
List(T),
|
|
49
49
|
/// Create an empty list.
|
|
50
50
|
new : (fn() -> Self)(
|
|
51
|
-
Self(_head
|
|
51
|
+
Self(_head :.None, _len : usize(0))
|
|
52
52
|
),
|
|
53
|
-
|
|
54
53
|
/// Return the number of elements.
|
|
55
54
|
len : (fn(self : Self) -> usize)(
|
|
56
55
|
self._len
|
|
57
56
|
),
|
|
58
|
-
|
|
59
57
|
/// Return `true` if the list is empty.
|
|
60
58
|
is_empty : (fn(self : Self) -> bool)(
|
|
61
|
-
|
|
59
|
+
self._len == usize(0)
|
|
62
60
|
),
|
|
63
|
-
|
|
64
61
|
/// Return a new list with `value` at the front. O(1).
|
|
65
62
|
prepend : (fn(self : Self, value : T) -> Self)(
|
|
66
63
|
Self(
|
|
67
|
-
_head
|
|
68
|
-
_len: (self._len + usize(1))
|
|
64
|
+
_head :.Some(ListNode(T)(_value : value, _next : self._head)),
|
|
65
|
+
_len : (self._len + usize(1))
|
|
69
66
|
)
|
|
70
67
|
),
|
|
71
|
-
|
|
72
68
|
/// Return the first element, or `.None` if empty. O(1).
|
|
73
69
|
head : (fn(self : Self) -> Option(T))(
|
|
74
|
-
match(
|
|
75
|
-
.
|
|
76
|
-
.
|
|
70
|
+
match(
|
|
71
|
+
self._head,
|
|
72
|
+
.Some(node) =>.Some(node._value),
|
|
73
|
+
.None =>.None
|
|
77
74
|
)
|
|
78
75
|
),
|
|
79
|
-
|
|
80
76
|
/// Return a new list without the first element. O(1).
|
|
81
77
|
/// Returns an empty list if already empty.
|
|
82
78
|
tail : (fn(self : Self) -> Self)(
|
|
83
|
-
match(
|
|
84
|
-
.
|
|
79
|
+
match(
|
|
80
|
+
self._head,
|
|
81
|
+
.Some(node) => Self(_head : node._next, _len : (self._len - usize(1))),
|
|
85
82
|
.None => self
|
|
86
83
|
)
|
|
87
84
|
),
|
|
88
|
-
|
|
89
85
|
/// Access element at `index`. O(n).
|
|
90
86
|
/// Returns `.None` if index is out of bounds.
|
|
91
87
|
get : (fn(self : Self, index : usize) -> Option(T))({
|
|
92
|
-
if(
|
|
93
|
-
return
|
|
88
|
+
if(index >= self._len, {
|
|
89
|
+
return(.None);
|
|
94
90
|
});
|
|
95
91
|
(current : Option(ListNode(T))) = self._head;
|
|
96
92
|
(i : usize) = usize(0);
|
|
97
|
-
while
|
|
98
|
-
match(
|
|
93
|
+
while(runtime(true), {
|
|
94
|
+
match(
|
|
95
|
+
current,
|
|
99
96
|
.Some(node) => {
|
|
100
|
-
if(
|
|
101
|
-
return
|
|
97
|
+
if(i == index, {
|
|
98
|
+
return(.Some(node._value));
|
|
102
99
|
});
|
|
103
100
|
current = node._next;
|
|
104
101
|
i = (i + usize(1));
|
|
105
102
|
},
|
|
106
103
|
.None => {
|
|
107
|
-
return
|
|
104
|
+
return(.None);
|
|
108
105
|
}
|
|
109
106
|
);
|
|
110
|
-
};
|
|
107
|
+
});
|
|
111
108
|
.None
|
|
112
109
|
}),
|
|
113
|
-
|
|
114
110
|
/// Return a new list with elements in reverse order. O(n).
|
|
115
111
|
reverse : (fn(self : Self) -> Self)({
|
|
116
112
|
(result : Self) = Self.new();
|
|
117
113
|
(current : Option(ListNode(T))) = self._head;
|
|
118
|
-
while
|
|
114
|
+
while(runtime(current.is_some()), {
|
|
119
115
|
(node : ListNode(T)) = current.unwrap();
|
|
120
116
|
result = result.prepend(node._value);
|
|
121
117
|
current = node._next;
|
|
122
|
-
};
|
|
118
|
+
});
|
|
123
119
|
result
|
|
124
120
|
}),
|
|
125
|
-
|
|
126
121
|
/// Concatenate two lists. O(n) where n = self.len().
|
|
127
122
|
/// The resulting list contains all elements of `self` followed by `other`.
|
|
128
123
|
concat : (fn(self : Self, other : Self) -> Self)({
|
|
129
124
|
reversed := self.reverse();
|
|
130
125
|
(result : Self) = other;
|
|
131
126
|
(current : Option(ListNode(T))) = reversed._head;
|
|
132
|
-
while
|
|
127
|
+
while(runtime(current.is_some()), {
|
|
133
128
|
(node : ListNode(T)) = current.unwrap();
|
|
134
129
|
result = result.prepend(node._value);
|
|
135
130
|
current = node._next;
|
|
136
|
-
};
|
|
131
|
+
});
|
|
137
132
|
result
|
|
138
133
|
}),
|
|
139
|
-
|
|
140
134
|
/// Apply a function to each element, producing a new list. O(n).
|
|
141
135
|
map : (fn(forall(U : Type), self : Self, f : Impl(Fn(a : T) -> U), where(U <: Send)) -> List(U))({
|
|
142
136
|
(result : List(U)) = List(U).new();
|
|
143
137
|
(current : Option(ListNode(T))) = self._head;
|
|
144
|
-
while
|
|
138
|
+
while(runtime(current.is_some()), {
|
|
145
139
|
(node : ListNode(T)) = current.unwrap();
|
|
146
140
|
result = result.prepend(f(node._value));
|
|
147
141
|
current = node._next;
|
|
148
|
-
};
|
|
142
|
+
});
|
|
149
143
|
result.reverse()
|
|
150
144
|
}),
|
|
151
|
-
|
|
152
145
|
/// Keep only elements satisfying the predicate. O(n).
|
|
153
146
|
filter : (fn(self : Self, f : Impl(Fn(a : T) -> bool)) -> Self)({
|
|
154
147
|
(result : Self) = Self.new();
|
|
155
148
|
(current : Option(ListNode(T))) = self._head;
|
|
156
|
-
while
|
|
149
|
+
while(runtime(current.is_some()), {
|
|
157
150
|
(node : ListNode(T)) = current.unwrap();
|
|
158
151
|
if(f(node._value), {
|
|
159
152
|
result = result.prepend(node._value);
|
|
160
153
|
});
|
|
161
154
|
current = node._next;
|
|
162
|
-
};
|
|
155
|
+
});
|
|
163
156
|
result.reverse()
|
|
164
157
|
}),
|
|
165
|
-
|
|
166
158
|
/// Left fold over the list. O(n).
|
|
167
159
|
fold : (fn(forall(U : Type), self : Self, init : U, f : Impl(Fn(acc : U, item : T) -> U)) -> U)({
|
|
168
160
|
(acc : U) = init;
|
|
169
161
|
(current : Option(ListNode(T))) = self._head;
|
|
170
|
-
while
|
|
162
|
+
while(runtime(current.is_some()), {
|
|
171
163
|
(node : ListNode(T)) = current.unwrap();
|
|
172
164
|
acc = f(acc, node._value);
|
|
173
165
|
current = node._next;
|
|
174
|
-
};
|
|
166
|
+
});
|
|
175
167
|
acc
|
|
176
168
|
}),
|
|
177
|
-
|
|
178
169
|
/// Execute a function for each element. O(n).
|
|
179
170
|
for_each : (fn(self : Self, f : Impl(Fn(a : T) -> unit)) -> unit)({
|
|
180
171
|
(current : Option(ListNode(T))) = self._head;
|
|
181
|
-
while
|
|
172
|
+
while(runtime(current.is_some()), {
|
|
182
173
|
(node : ListNode(T)) = current.unwrap();
|
|
183
174
|
f(node._value);
|
|
184
175
|
current = node._next;
|
|
185
|
-
};
|
|
176
|
+
});
|
|
186
177
|
}),
|
|
187
|
-
|
|
188
178
|
/// Check if the list contains a value. O(n).
|
|
189
179
|
/// Requires T to implement Eq.
|
|
190
180
|
contains : (fn(self : Self, value : T, where(T <: Eq(T))) -> bool)({
|
|
191
181
|
(current : Option(ListNode(T))) = self._head;
|
|
192
|
-
while
|
|
193
|
-
match(
|
|
182
|
+
while(runtime(true), {
|
|
183
|
+
match(
|
|
184
|
+
current,
|
|
194
185
|
.Some(node) => {
|
|
195
|
-
if(
|
|
196
|
-
return
|
|
186
|
+
if(node._value == value, {
|
|
187
|
+
return(true);
|
|
197
188
|
});
|
|
198
189
|
current = node._next;
|
|
199
190
|
},
|
|
200
191
|
.None => {
|
|
201
|
-
return
|
|
192
|
+
return(false);
|
|
202
193
|
}
|
|
203
194
|
);
|
|
204
|
-
};
|
|
195
|
+
});
|
|
205
196
|
false
|
|
206
197
|
}),
|
|
207
|
-
|
|
208
198
|
/// Build a list from a slice. O(n).
|
|
209
199
|
from_slice : (fn(s : Slice(T)) -> Self)({
|
|
210
200
|
(result : Self) = Self.new();
|
|
211
201
|
(i : usize) = s.len();
|
|
212
|
-
while
|
|
202
|
+
while(i > usize(0), {
|
|
213
203
|
i = (i - usize(1));
|
|
214
204
|
result = result.prepend(s(i));
|
|
215
|
-
};
|
|
205
|
+
});
|
|
216
206
|
result
|
|
217
207
|
})
|
|
218
208
|
);
|
|
219
|
-
|
|
220
209
|
/// Equality: two lists are equal if they have the same length and elements.
|
|
221
|
-
impl(
|
|
222
|
-
(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
r
|
|
237
|
-
|
|
210
|
+
impl(
|
|
211
|
+
forall(T : Type),
|
|
212
|
+
where(T <: (Send, Eq(T))),
|
|
213
|
+
List(T),
|
|
214
|
+
Eq(List(T))(
|
|
215
|
+
(==) : (fn(lhs : Self, rhs : Self) -> bool)({
|
|
216
|
+
if(lhs._len != rhs._len, {
|
|
217
|
+
return(false);
|
|
218
|
+
});
|
|
219
|
+
(l : Option(ListNode(T))) = lhs._head;
|
|
220
|
+
(r : Option(ListNode(T))) = rhs._head;
|
|
221
|
+
while(runtime(true), {
|
|
222
|
+
match(
|
|
223
|
+
l,
|
|
224
|
+
.Some(ln) => match(
|
|
225
|
+
r,
|
|
226
|
+
.Some(rn) => {
|
|
227
|
+
if(ln._value != rn._value, {
|
|
228
|
+
return(false);
|
|
229
|
+
});
|
|
230
|
+
l = ln._next;
|
|
231
|
+
r = rn._next;
|
|
232
|
+
},
|
|
233
|
+
.None => {
|
|
234
|
+
return(false);
|
|
235
|
+
}
|
|
236
|
+
),
|
|
238
237
|
.None => {
|
|
239
|
-
return
|
|
238
|
+
return(true);
|
|
240
239
|
}
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
})
|
|
249
|
-
));
|
|
250
|
-
|
|
251
|
-
export
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
true
|
|
243
|
+
})
|
|
244
|
+
)
|
|
245
|
+
);
|
|
246
|
+
export(
|
|
252
247
|
List,
|
|
253
248
|
ListNode
|
|
254
|
-
;
|
|
249
|
+
);
|