@shd101wyy/yo 0.1.12 → 0.1.13
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/README.md +10 -1
- package/out/cjs/index.cjs +578 -572
- package/out/cjs/yo-cli.cjs +1413 -592
- package/out/esm/index.mjs +434 -428
- package/out/types/src/build-runner.d.ts +1 -1
- package/out/types/src/doc/builder.d.ts +21 -0
- package/out/types/src/doc/builder.test.d.ts +1 -0
- package/out/types/src/doc/extractor.d.ts +27 -0
- package/out/types/src/doc/extractor.test.d.ts +1 -0
- package/out/types/src/doc/model.d.ts +87 -0
- package/out/types/src/doc/render-html.d.ts +23 -0
- package/out/types/src/doc/render-html.test.d.ts +1 -0
- package/out/types/src/doc/render-json.d.ts +7 -0
- package/out/types/src/doc/render-json.test.d.ts +1 -0
- package/out/types/src/doc/render-markdown.d.ts +13 -0
- package/out/types/src/doc/render-markdown.test.d.ts +1 -0
- package/out/types/src/doc/sections.d.ts +7 -0
- package/out/types/src/doc/sections.test.d.ts +1 -0
- package/out/types/src/doc-command.d.ts +10 -0
- package/out/types/src/env.d.ts +1 -0
- package/out/types/src/evaluator/builtins/build.d.ts +17 -0
- package/out/types/src/evaluator/context.d.ts +1 -0
- package/out/types/src/expr.d.ts +2 -1
- package/out/types/src/token.d.ts +4 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/scripts/build-site.ts +461 -0
- package/std/alg/hash.yo +12 -24
- package/std/allocator.yo +21 -29
- package/std/async.yo +4 -2
- package/std/build.yo +188 -42
- package/std/cli/arg_parser.yo +37 -1
- package/std/collections/array_list.yo +8 -20
- package/std/collections/btree_map.yo +15 -20
- package/std/collections/deque.yo +13 -15
- package/std/collections/hash_map.yo +15 -54
- package/std/collections/hash_set.yo +14 -50
- package/std/collections/linked_list.yo +6 -23
- package/std/collections/priority_queue.yo +15 -17
- package/std/crypto/md5.yo +10 -9
- package/std/crypto/random.yo +14 -12
- package/std/crypto/sha256.yo +9 -8
- package/std/encoding/base64.yo +13 -15
- package/std/encoding/hex.yo +14 -10
- package/std/encoding/html.yo +14 -11
- package/std/encoding/html_char_utils.yo +14 -11
- package/std/encoding/html_entities.yo +7 -8
- package/std/encoding/json.yo +36 -19
- package/std/encoding/punycode.yo +21 -18
- package/std/encoding/toml.yo +23 -9
- package/std/encoding/utf16.yo +16 -9
- package/std/error.yo +10 -23
- package/std/fmt/display.yo +15 -17
- package/std/fmt/index.yo +6 -27
- package/std/fmt/to_string.yo +4 -10
- package/std/fmt/writer.yo +33 -34
- package/std/fs/dir.yo +37 -30
- package/std/fs/file.yo +77 -75
- package/std/fs/metadata.yo +25 -25
- package/std/fs/temp.yo +21 -27
- package/std/fs/types.yo +20 -23
- package/std/fs/walker.yo +26 -31
- package/std/gc.yo +5 -0
- package/std/glob/index.yo +3 -0
- package/std/http/client.yo +25 -11
- package/std/http/http.yo +20 -0
- package/std/http/index.yo +1 -0
- package/std/io/reader.yo +4 -8
- package/std/io/writer.yo +4 -7
- package/std/libc/assert.yo +2 -2
- package/std/libc/ctype.yo +1 -2
- package/std/libc/dirent.yo +1 -2
- package/std/libc/errno.yo +1 -2
- package/std/libc/fcntl.yo +2 -2
- package/std/libc/float.yo +1 -2
- package/std/libc/limits.yo +1 -2
- package/std/libc/math.yo +2 -0
- package/std/libc/signal.yo +1 -2
- package/std/libc/stdatomic.yo +1 -2
- package/std/libc/stdint.yo +4 -3
- package/std/libc/stdio.yo +2 -0
- package/std/libc/stdlib.yo +2 -0
- package/std/libc/string.yo +2 -0
- package/std/libc/sys/stat.yo +1 -2
- package/std/libc/time.yo +2 -2
- package/std/libc/unistd.yo +2 -0
- package/std/libc/wctype.yo +1 -2
- package/std/libc/windows.yo +2 -2
- package/std/log/index.yo +11 -26
- package/std/net/addr.yo +18 -11
- package/std/net/dns.yo +3 -2
- package/std/net/errors.yo +16 -2
- package/std/net/tcp.yo +25 -22
- package/std/net/udp.yo +14 -12
- package/std/os/env.yo +23 -18
- package/std/os/signal.yo +31 -19
- package/std/path.yo +23 -74
- package/std/prelude.yo +284 -113
- package/std/process.yo +23 -37
- package/std/regex/compiler.yo +3 -5
- package/std/regex/flags.yo +11 -11
- package/std/regex/index.yo +2 -13
- package/std/regex/match.yo +3 -5
- package/std/regex/node.yo +6 -6
- package/std/regex/parser.yo +2 -4
- package/std/regex/unicode.yo +5 -5
- package/std/regex/vm.yo +5 -5
- package/std/string/index.yo +2 -1
- package/std/string/rune.yo +25 -1
- package/std/string/string.yo +31 -19
- package/std/string/unicode.yo +14 -15
- package/std/sync/channel.yo +18 -28
- package/std/sync/cond.yo +4 -0
- package/std/sync/mutex.yo +4 -1
- package/std/sync/once.yo +17 -19
- package/std/sync/rwlock.yo +19 -22
- package/std/sync/waitgroup.yo +21 -23
- package/std/sys/advise.yo +4 -4
- package/std/sys/bufio/buf_reader.yo +19 -16
- package/std/sys/bufio/buf_writer.yo +14 -11
- package/std/sys/clock.yo +4 -4
- package/std/sys/constants.yo +5 -5
- package/std/sys/copy.yo +9 -8
- package/std/sys/dir.yo +9 -8
- package/std/sys/dns.yo +8 -8
- package/std/sys/errors.yo +35 -6
- package/std/sys/events.yo +3 -3
- package/std/sys/externs.yo +3 -3
- package/std/sys/fallocate.yo +4 -4
- package/std/sys/fcntl.yo +8 -6
- package/std/sys/file.yo +7 -8
- package/std/sys/future.yo +1 -3
- package/std/sys/iov.yo +4 -4
- package/std/sys/lock.yo +7 -7
- package/std/sys/mmap.yo +7 -8
- package/std/sys/path.yo +4 -7
- package/std/sys/perm.yo +8 -8
- package/std/sys/pipe.yo +9 -8
- package/std/sys/process.yo +8 -8
- package/std/sys/seek.yo +4 -4
- package/std/sys/signal.yo +4 -4
- package/std/sys/signals.yo +4 -4
- package/std/sys/socket.yo +4 -4
- package/std/sys/socketpair.yo +4 -4
- package/std/sys/sockinfo.yo +4 -4
- package/std/sys/statfs.yo +8 -8
- package/std/sys/statx.yo +4 -4
- package/std/sys/sysinfo.yo +4 -4
- package/std/sys/tcp.yo +8 -8
- package/std/sys/temp.yo +9 -8
- package/std/sys/time.yo +8 -8
- package/std/sys/timer.yo +7 -8
- package/std/sys/tty.yo +13 -10
- package/std/sys/udp.yo +8 -8
- package/std/sys/umask.yo +4 -4
- package/std/sys/unix.yo +5 -5
- package/std/testing/bench.yo +21 -10
- package/std/thread.yo +18 -9
- package/std/time/datetime.yo +12 -14
- package/std/time/duration.yo +12 -14
- package/std/time/instant.yo +13 -16
- package/std/time/sleep.yo +9 -8
- package/std/url/index.yo +3 -19
- package/std/worker.yo +10 -18
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shd101wyy/yo",
|
|
3
3
|
"displayName": "Yo",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.13",
|
|
5
5
|
"main": "./out/cjs/index.cjs",
|
|
6
6
|
"module": "./out/esm/index.mjs",
|
|
7
7
|
"types": "./out/types/src/index.d.ts",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
]
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
+
"markdown_yo": "0.0.4",
|
|
50
51
|
"yargs": "^17.7.2"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Build the documentation website for https://shd101wyy.github.io/Yo/
|
|
4
|
+
*
|
|
5
|
+
* Output structure:
|
|
6
|
+
* site/
|
|
7
|
+
* index.html ← README.md rendered as HTML (homepage)
|
|
8
|
+
* Yo_logo.png ← copied logo
|
|
9
|
+
* std/ ← generated std library docs
|
|
10
|
+
* index.html ← std library index
|
|
11
|
+
* module/ ← per-module pages
|
|
12
|
+
* string.html
|
|
13
|
+
* ...
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* bun run scripts/build-site.ts [--output <dir>]
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import * as fs from "fs";
|
|
20
|
+
import * as path from "path";
|
|
21
|
+
import { createRenderer } from "markdown_yo";
|
|
22
|
+
import type { MarkdownRenderer } from "markdown_yo";
|
|
23
|
+
import { execSync } from "child_process";
|
|
24
|
+
|
|
25
|
+
const ROOT = path.resolve(import.meta.dir, "..");
|
|
26
|
+
const GITHUB_REPO = "https://github.com/shd101wyy/Yo";
|
|
27
|
+
|
|
28
|
+
// Detect the latest release tag for stable links.
|
|
29
|
+
// Falls back to "main" if no tags exist or git fails.
|
|
30
|
+
function getLatestTag(): string {
|
|
31
|
+
try {
|
|
32
|
+
const result = execSync("git describe --tags --abbrev=0 2>/dev/null", {
|
|
33
|
+
cwd: ROOT,
|
|
34
|
+
encoding: "utf-8",
|
|
35
|
+
timeout: 5000,
|
|
36
|
+
}).trim();
|
|
37
|
+
return result || "main";
|
|
38
|
+
} catch {
|
|
39
|
+
return "main";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const GITHUB_REF = getLatestTag();
|
|
44
|
+
const GITHUB_BLOB = `${GITHUB_REPO}/blob/${GITHUB_REF}`;
|
|
45
|
+
|
|
46
|
+
// ── Parse args ───────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
let outputDir = path.join(ROOT, "site");
|
|
49
|
+
const args = process.argv.slice(2);
|
|
50
|
+
for (let i = 0; i < args.length; i++) {
|
|
51
|
+
if (args[i] === "--output" && args[i + 1]) {
|
|
52
|
+
outputDir = path.resolve(args[i + 1]!);
|
|
53
|
+
i++;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
function escapeHtml(s: string): string {
|
|
60
|
+
return s
|
|
61
|
+
.replace(/&/g, "&")
|
|
62
|
+
.replace(/</g, "<")
|
|
63
|
+
.replace(/>/g, ">")
|
|
64
|
+
.replace(/"/g, """);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Rewrite relative links in the README for the deployed site.
|
|
69
|
+
*
|
|
70
|
+
* - `./Yo_logo.png` → `Yo_logo.png` (local asset)
|
|
71
|
+
* - `./docs/en-US/X.md` → GitHub blob link
|
|
72
|
+
* - `./docs/zh-CN/X.md` → GitHub blob link
|
|
73
|
+
* - `./vscode-extension/...` → GitHub blob link
|
|
74
|
+
* - `./plans/...` → GitHub blob link
|
|
75
|
+
* - `https://shd101wyy.github.io/Yo/` → `std/index.html` (relative, same site)
|
|
76
|
+
* - `#anchor` links → kept as-is
|
|
77
|
+
*/
|
|
78
|
+
function rewriteReadmeLinks(html: string): string {
|
|
79
|
+
// Rewrite the generated docs link to relative std/ path (same site)
|
|
80
|
+
html = html.replace(
|
|
81
|
+
/href="https:\/\/shd101wyy\.github\.io\/Yo\/"/g,
|
|
82
|
+
'href="std/index.html"'
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Rewrite href links — any relative path that isn't an anchor, absolute URL,
|
|
86
|
+
// or our own site paths (std/) gets rewritten to GitHub blob links.
|
|
87
|
+
html = html.replace(/href="([^"]+)"/g, (_match: string, href: string) => {
|
|
88
|
+
// Keep absolute URLs, anchors, and std/ links
|
|
89
|
+
if (
|
|
90
|
+
href.startsWith("http") ||
|
|
91
|
+
href.startsWith("#") ||
|
|
92
|
+
href.startsWith("std/") ||
|
|
93
|
+
href.startsWith("mailto:")
|
|
94
|
+
) {
|
|
95
|
+
return _match;
|
|
96
|
+
}
|
|
97
|
+
// Strip leading "./" if present
|
|
98
|
+
const relPath = href.startsWith("./") ? href.slice(2) : href;
|
|
99
|
+
// Keep local assets that we copy to the site
|
|
100
|
+
if (relPath === "Yo_logo.png" || relPath === "path_uniqueness.png") {
|
|
101
|
+
return `href="${relPath}"`;
|
|
102
|
+
}
|
|
103
|
+
// Rewrite to GitHub
|
|
104
|
+
return `href="${GITHUB_BLOB}/${relPath}"`;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Rewrite src links (images)
|
|
108
|
+
html = html.replace(/src="([^"]+)"/g, (_match: string, src: string) => {
|
|
109
|
+
if (src.startsWith("http")) return _match;
|
|
110
|
+
const relPath = src.startsWith("./") ? src.slice(2) : src;
|
|
111
|
+
if (relPath === "Yo_logo.png" || relPath === "path_uniqueness.png") {
|
|
112
|
+
return `src="${relPath}"`;
|
|
113
|
+
}
|
|
114
|
+
return `src="${GITHUB_BLOB}/${relPath}?raw=true"`;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return html;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function generateHomepageCSS(): string {
|
|
121
|
+
return `
|
|
122
|
+
:root {
|
|
123
|
+
--bg: #fff;
|
|
124
|
+
--bg-code: #f7f7f7;
|
|
125
|
+
--bg-code-block: #282c34;
|
|
126
|
+
--text: #1a1a1a;
|
|
127
|
+
--text-secondary: #555;
|
|
128
|
+
--text-code: #abb2bf;
|
|
129
|
+
--accent: #4a90d9;
|
|
130
|
+
--accent-hover: #357abd;
|
|
131
|
+
--border: #e0e0e0;
|
|
132
|
+
--border-light: #eee;
|
|
133
|
+
--shadow: rgba(0,0,0,0.05);
|
|
134
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
135
|
+
--font-mono: "SF Mono", "Cascadia Code", "Fira Code", "JetBrains Mono", Consolas, monospace;
|
|
136
|
+
--max-content: 860px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@media (prefers-color-scheme: dark) {
|
|
140
|
+
:root {
|
|
141
|
+
--bg: #1a1a2e;
|
|
142
|
+
--bg-code: #0f3460;
|
|
143
|
+
--bg-code-block: #1e1e2e;
|
|
144
|
+
--text: #e0e0e0;
|
|
145
|
+
--text-secondary: #a0a0a0;
|
|
146
|
+
--text-code: #abb2bf;
|
|
147
|
+
--accent: #6cb4ee;
|
|
148
|
+
--accent-hover: #8fcbff;
|
|
149
|
+
--border: #2a2a4a;
|
|
150
|
+
--border-light: #252545;
|
|
151
|
+
--shadow: rgba(0,0,0,0.2);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
156
|
+
|
|
157
|
+
body {
|
|
158
|
+
font-family: var(--font-sans);
|
|
159
|
+
font-size: 16px;
|
|
160
|
+
line-height: 1.7;
|
|
161
|
+
color: var(--text);
|
|
162
|
+
background: var(--bg);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.container {
|
|
166
|
+
max-width: var(--max-content);
|
|
167
|
+
margin: 0 auto;
|
|
168
|
+
padding: 40px 24px 80px;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* Typography */
|
|
172
|
+
h1 { font-size: 2.2em; margin: 1em 0 0.5em; border-bottom: 2px solid var(--border); padding-bottom: 0.3em; }
|
|
173
|
+
h2 { font-size: 1.6em; margin: 1.5em 0 0.5em; border-bottom: 1px solid var(--border-light); padding-bottom: 0.2em; }
|
|
174
|
+
h3 { font-size: 1.3em; margin: 1.2em 0 0.4em; }
|
|
175
|
+
h4 { font-size: 1.1em; margin: 1em 0 0.3em; }
|
|
176
|
+
p { margin: 0.8em 0; }
|
|
177
|
+
ul, ol { margin: 0.8em 0 0.8em 1.5em; }
|
|
178
|
+
li { margin: 0.3em 0; }
|
|
179
|
+
|
|
180
|
+
a { color: var(--accent); text-decoration: none; }
|
|
181
|
+
a:hover { color: var(--accent-hover); text-decoration: underline; }
|
|
182
|
+
|
|
183
|
+
img { max-width: 100%; height: auto; }
|
|
184
|
+
|
|
185
|
+
code {
|
|
186
|
+
font-family: var(--font-mono);
|
|
187
|
+
font-size: 0.9em;
|
|
188
|
+
background: var(--bg-code);
|
|
189
|
+
padding: 0.15em 0.4em;
|
|
190
|
+
border-radius: 4px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
pre {
|
|
194
|
+
background: var(--bg-code-block);
|
|
195
|
+
color: var(--text-code);
|
|
196
|
+
padding: 16px 20px;
|
|
197
|
+
border-radius: 8px;
|
|
198
|
+
overflow-x: auto;
|
|
199
|
+
margin: 1em 0;
|
|
200
|
+
font-size: 0.9em;
|
|
201
|
+
line-height: 1.5;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
pre code {
|
|
205
|
+
background: none;
|
|
206
|
+
padding: 0;
|
|
207
|
+
color: inherit;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
blockquote {
|
|
211
|
+
border-left: 4px solid var(--accent);
|
|
212
|
+
margin: 1em 0;
|
|
213
|
+
padding: 0.5em 1em;
|
|
214
|
+
background: var(--bg-code);
|
|
215
|
+
border-radius: 0 4px 4px 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
table {
|
|
219
|
+
border-collapse: collapse;
|
|
220
|
+
width: 100%;
|
|
221
|
+
margin: 1em 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
th, td {
|
|
225
|
+
border: 1px solid var(--border);
|
|
226
|
+
padding: 8px 12px;
|
|
227
|
+
text-align: left;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
th {
|
|
231
|
+
background: var(--bg-code);
|
|
232
|
+
font-weight: 600;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Header banner */
|
|
236
|
+
.site-header {
|
|
237
|
+
text-align: center;
|
|
238
|
+
padding: 30px 0 20px;
|
|
239
|
+
border-bottom: 2px solid var(--border);
|
|
240
|
+
margin-bottom: 30px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.site-header img {
|
|
244
|
+
width: 80px;
|
|
245
|
+
height: 80px;
|
|
246
|
+
margin-bottom: 10px;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.site-header h1 {
|
|
250
|
+
border: none;
|
|
251
|
+
margin: 0;
|
|
252
|
+
padding: 0;
|
|
253
|
+
font-size: 2.5em;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.site-header .tagline {
|
|
257
|
+
color: var(--text-secondary);
|
|
258
|
+
font-size: 1.1em;
|
|
259
|
+
margin-top: 8px;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.site-nav {
|
|
263
|
+
margin-top: 16px;
|
|
264
|
+
display: flex;
|
|
265
|
+
gap: 16px;
|
|
266
|
+
justify-content: center;
|
|
267
|
+
flex-wrap: wrap;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.site-nav a {
|
|
271
|
+
display: inline-block;
|
|
272
|
+
padding: 6px 16px;
|
|
273
|
+
background: var(--accent);
|
|
274
|
+
color: #fff;
|
|
275
|
+
border-radius: 6px;
|
|
276
|
+
font-weight: 500;
|
|
277
|
+
font-size: 0.95em;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.site-nav a:hover {
|
|
281
|
+
background: var(--accent-hover);
|
|
282
|
+
text-decoration: none;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* Footer */
|
|
286
|
+
.site-footer {
|
|
287
|
+
text-align: center;
|
|
288
|
+
padding: 30px 0;
|
|
289
|
+
margin-top: 60px;
|
|
290
|
+
border-top: 1px solid var(--border);
|
|
291
|
+
color: var(--text-secondary);
|
|
292
|
+
font-size: 0.9em;
|
|
293
|
+
}
|
|
294
|
+
`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function wrapHomepage(title: string, bodyHtml: string, css: string): string {
|
|
298
|
+
return `<!DOCTYPE html>
|
|
299
|
+
<html lang="en">
|
|
300
|
+
<head>
|
|
301
|
+
<meta charset="utf-8">
|
|
302
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
303
|
+
<title>${escapeHtml(title)}</title>
|
|
304
|
+
<style>${css}</style>
|
|
305
|
+
</head>
|
|
306
|
+
<body>
|
|
307
|
+
<div class="container">
|
|
308
|
+
<div class="site-header">
|
|
309
|
+
<img src="Yo_logo.png" alt="Yo logo" width="80" height="80">
|
|
310
|
+
<h1>Yo Programming Language</h1>
|
|
311
|
+
<p class="tagline">A general-purpose, ahead-of-time compiled language with algebraic effects</p>
|
|
312
|
+
<div class="site-nav">
|
|
313
|
+
<a href="${GITHUB_REPO}">GitHub</a>
|
|
314
|
+
<a href="std/index.html">Standard Library</a>
|
|
315
|
+
<a href="${GITHUB_BLOB}/docs/en-US/DESIGN.md">Language Design</a>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
<div class="readme-content">
|
|
319
|
+
${bodyHtml}
|
|
320
|
+
</div>
|
|
321
|
+
<div class="site-footer">
|
|
322
|
+
<p>Yo Programming Language — <a href="${GITHUB_REPO}">GitHub</a> · <a href="std/index.html">Std Library Docs</a></p>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</body>
|
|
326
|
+
</html>`;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Post-process generated std doc HTML files to add a "← Home" link
|
|
331
|
+
* in the sidebar header, pointing back to the main site homepage.
|
|
332
|
+
*/
|
|
333
|
+
function injectHomeLinks(stdDir: string): void {
|
|
334
|
+
const homeLink = `<a href="../index.html" style="display:block;margin-bottom:8px;font-size:0.85em;color:var(--text-secondary);text-decoration:none;">← Home</a>`;
|
|
335
|
+
const homeLinkFromModule = `<a href="../../index.html" style="display:block;margin-bottom:8px;font-size:0.85em;color:var(--text-secondary);text-decoration:none;">← Home</a>`;
|
|
336
|
+
|
|
337
|
+
// Process std/index.html
|
|
338
|
+
const indexPath = path.join(stdDir, "index.html");
|
|
339
|
+
if (fs.existsSync(indexPath)) {
|
|
340
|
+
let content = fs.readFileSync(indexPath, "utf-8");
|
|
341
|
+
content = content.replace(
|
|
342
|
+
'<div class="sidebar-header">',
|
|
343
|
+
`<div class="sidebar-header">\n ${homeLink}`
|
|
344
|
+
);
|
|
345
|
+
fs.writeFileSync(indexPath, content, "utf-8");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Process std/module/*.html
|
|
349
|
+
const moduleDir = path.join(stdDir, "module");
|
|
350
|
+
if (fs.existsSync(moduleDir)) {
|
|
351
|
+
for (const file of fs.readdirSync(moduleDir)) {
|
|
352
|
+
if (!file.endsWith(".html")) continue;
|
|
353
|
+
const filePath = path.join(moduleDir, file);
|
|
354
|
+
let content = fs.readFileSync(filePath, "utf-8");
|
|
355
|
+
content = content.replace(
|
|
356
|
+
'<div class="sidebar-header">',
|
|
357
|
+
`<div class="sidebar-header">\n ${homeLinkFromModule}`
|
|
358
|
+
);
|
|
359
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ── Main ─────────────────────────────────────────────────────────────
|
|
365
|
+
|
|
366
|
+
async function main(): Promise<void> {
|
|
367
|
+
console.log("Building documentation site...");
|
|
368
|
+
console.log(` Output: ${outputDir}`);
|
|
369
|
+
|
|
370
|
+
// Clean and create output directory
|
|
371
|
+
if (fs.existsSync(outputDir)) {
|
|
372
|
+
fs.rmSync(outputDir, { recursive: true });
|
|
373
|
+
}
|
|
374
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
375
|
+
|
|
376
|
+
// ── Step 1: Render README.md as homepage ──
|
|
377
|
+
console.log("\n[1/3] Rendering homepage from README.md...");
|
|
378
|
+
const readmeSrc = fs.readFileSync(path.join(ROOT, "README.md"), "utf-8");
|
|
379
|
+
|
|
380
|
+
const md: MarkdownRenderer = await createRenderer(null, {
|
|
381
|
+
html: true,
|
|
382
|
+
fullFeatures: true,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
let readmeHtml = md.render(readmeSrc);
|
|
386
|
+
readmeHtml = rewriteReadmeLinks(readmeHtml);
|
|
387
|
+
|
|
388
|
+
const css = generateHomepageCSS();
|
|
389
|
+
const homepage = wrapHomepage("Yo Programming Language", readmeHtml, css);
|
|
390
|
+
fs.writeFileSync(path.join(outputDir, "index.html"), homepage, "utf-8");
|
|
391
|
+
console.log(" ✓ index.html");
|
|
392
|
+
|
|
393
|
+
md.destroy();
|
|
394
|
+
|
|
395
|
+
// ── Step 2: Copy static assets ──
|
|
396
|
+
console.log("\n[2/3] Copying static assets...");
|
|
397
|
+
const logoSrc = path.join(ROOT, "Yo_logo.png");
|
|
398
|
+
if (fs.existsSync(logoSrc)) {
|
|
399
|
+
fs.copyFileSync(logoSrc, path.join(outputDir, "Yo_logo.png"));
|
|
400
|
+
console.log(" ✓ Yo_logo.png");
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Copy path_uniqueness.png if it exists (referenced in README)
|
|
404
|
+
const pathUniqSrc = path.join(ROOT, "path_uniqueness.png");
|
|
405
|
+
if (fs.existsSync(pathUniqSrc)) {
|
|
406
|
+
fs.copyFileSync(pathUniqSrc, path.join(outputDir, "path_uniqueness.png"));
|
|
407
|
+
console.log(" ✓ path_uniqueness.png");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ── Step 3: Generate std library docs ──
|
|
411
|
+
console.log("\n[3/3] Generating standard library documentation...");
|
|
412
|
+
const stdOutputDir = path.join(outputDir, "std");
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const yoCli = path.join(ROOT, "yo-cli");
|
|
416
|
+
execSync(`${yoCli} doc std/ --output "${stdOutputDir}"`, {
|
|
417
|
+
cwd: ROOT,
|
|
418
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
419
|
+
timeout: 120_000,
|
|
420
|
+
});
|
|
421
|
+
console.log(" ✓ Standard library docs generated");
|
|
422
|
+
} catch (err) {
|
|
423
|
+
console.error(
|
|
424
|
+
" ✗ Failed to generate std docs:",
|
|
425
|
+
err instanceof Error ? err.message : String(err)
|
|
426
|
+
);
|
|
427
|
+
process.exit(1);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Post-process std docs: inject "← Home" link in sidebar headers
|
|
431
|
+
injectHomeLinks(stdOutputDir);
|
|
432
|
+
|
|
433
|
+
// ── Summary ──
|
|
434
|
+
const moduleCount = fs.existsSync(path.join(stdOutputDir, "module"))
|
|
435
|
+
? fs.readdirSync(path.join(stdOutputDir, "module")).length
|
|
436
|
+
: 0;
|
|
437
|
+
console.log(`\n✓ Site built successfully!`);
|
|
438
|
+
console.log(` Homepage: ${outputDir}/index.html`);
|
|
439
|
+
console.log(
|
|
440
|
+
` Std docs: ${stdOutputDir}/index.html (${moduleCount} modules)`
|
|
441
|
+
);
|
|
442
|
+
console.log(` Total size: ${getTotalSize(outputDir)} KB`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function getTotalSize(dir: string): number {
|
|
446
|
+
let total = 0;
|
|
447
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
448
|
+
const fullPath = path.join(dir, entry.name);
|
|
449
|
+
if (entry.isDirectory()) {
|
|
450
|
+
total += getTotalSize(fullPath);
|
|
451
|
+
} else {
|
|
452
|
+
total += fs.statSync(fullPath).size;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return Math.round(total / 1024);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
main().catch((err) => {
|
|
459
|
+
console.error("Fatal error:", err);
|
|
460
|
+
process.exit(1);
|
|
461
|
+
});
|
package/std/alg/hash.yo
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* - FNV_PRIME: 1099511628211 (0x100000001b3)
|
|
8
|
-
*/
|
|
1
|
+
//! FNV-1a (Fowler-Noll-Vo) hash function.
|
|
2
|
+
//!
|
|
3
|
+
//! A fast, non-cryptographic hash function with good distribution.
|
|
4
|
+
//! Used internally by `HashMap` and `HashSet`.
|
|
5
|
+
|
|
6
|
+
/// FNV offset basis constant (0xcbf29ce484222325).
|
|
9
7
|
FNV_OFFSET_BASIS :: u64(14695981039346656037);
|
|
8
|
+
/// FNV prime constant (0x100000001b3).
|
|
10
9
|
FNV_PRIME :: u64(1099511628211);
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
* Hash a sequence of bytes using FNV-1a
|
|
14
|
-
* This is the core hash function used for most types
|
|
15
|
-
*/
|
|
11
|
+
/// Hash a byte sequence using FNV-1a.
|
|
16
12
|
fnv1a_hash_bytes :: (fn(bytes: *(u8), length: usize) -> u64)
|
|
17
13
|
{
|
|
18
14
|
hash := FNV_OFFSET_BASIS;
|
|
@@ -26,18 +22,10 @@ fnv1a_hash_bytes :: (fn(bytes: *(u8), length: usize) -> u64)
|
|
|
26
22
|
}
|
|
27
23
|
;
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* This uses a simple but effective mixing function:
|
|
34
|
-
* hash = hash * 31 + other_hash
|
|
35
|
-
*
|
|
36
|
-
* The constant 31 is chosen because:
|
|
37
|
-
* - It's prime (better distribution)
|
|
38
|
-
* - It's close to a power of 2 (fast multiplication)
|
|
39
|
-
* - It's been proven effective in Java's hashCode()
|
|
40
|
-
*/
|
|
25
|
+
/// Combine two hash values using `hash * 31 + other`.
|
|
26
|
+
///
|
|
27
|
+
/// The constant 31 is chosen because it is prime, close to a power of 2
|
|
28
|
+
/// (fast multiplication), and proven effective in practice.
|
|
41
29
|
hash_combine :: (fn(hash: u64, other: u64) -> u64)
|
|
42
30
|
((hash * u64(31)) + other)
|
|
43
31
|
;
|
package/std/allocator.yo
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
|
+
//! Memory allocation abstractions and global allocator interface.
|
|
2
|
+
|
|
1
3
|
{ SIZE_MAX } :: import "./libc/stdint.yo";
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
* Allocation error types
|
|
5
|
-
*/
|
|
5
|
+
/// Memory allocation error variants.
|
|
6
6
|
AllocError :: enum(
|
|
7
|
+
/// Allocator ran out of memory.
|
|
7
8
|
OutOfMemory,
|
|
9
|
+
/// Requested size is invalid (e.g., zero or too large).
|
|
8
10
|
InvalidSize,
|
|
11
|
+
/// Requested alignment is not a power of two.
|
|
9
12
|
InvalidAlignment,
|
|
13
|
+
/// Pointer passed to dealloc/realloc is invalid.
|
|
10
14
|
InvalidPointer
|
|
11
15
|
);
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
* Memory layout information for a type
|
|
15
|
-
*/
|
|
17
|
+
/// Describes the size and alignment requirements for a memory allocation.
|
|
16
18
|
Layout :: struct(
|
|
19
|
+
/// Size in bytes.
|
|
17
20
|
size: usize,
|
|
21
|
+
/// Alignment in bytes (must be a power of two).
|
|
18
22
|
alignment: usize
|
|
19
23
|
);
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
* Get the memory layout for a type T
|
|
23
|
-
*/
|
|
25
|
+
/// Get the memory layout (size and alignment) of a type at compile time.
|
|
24
26
|
layout_of ::
|
|
25
27
|
(fn(comptime(T): Type) -> comptime(Layout))
|
|
26
28
|
Layout(
|
|
@@ -29,9 +31,7 @@ layout_of ::
|
|
|
29
31
|
)
|
|
30
32
|
;
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
* Check if a size calculation would overflow
|
|
34
|
-
*/
|
|
34
|
+
/// Check if allocating `count` elements of type T would overflow `usize`.
|
|
35
35
|
size_would_overflow ::
|
|
36
36
|
(fn(comptime(T): Type, count: usize) -> bool) {
|
|
37
37
|
type_size :: sizeof(T);
|
|
@@ -41,37 +41,28 @@ size_would_overflow ::
|
|
|
41
41
|
)
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
/// User-implementable memory allocator interface.
|
|
45
|
+
/// Implement this trait to provide custom allocation strategies.
|
|
44
46
|
CustomAllocator :: trait(
|
|
45
|
-
|
|
46
|
-
* Allocate memory for count times of type T.
|
|
47
|
-
*/
|
|
47
|
+
/// Allocate memory for `count` items of type T.
|
|
48
48
|
alloc : (fn(self : *(Self), comptime(T): Type, count: usize) -> Result(?*(T), AllocError)),
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
* Allocate zeroed memory for count items of type T
|
|
52
|
-
*/
|
|
50
|
+
/// Allocate zeroed memory for `count` items of type T.
|
|
53
51
|
alloc_zeroed : (fn(self : *(Self), comptime(T): Type, count: usize) -> Result(?*(T), AllocError)),
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
* Allocate aligned memory for count items of type T
|
|
57
|
-
*/
|
|
53
|
+
/// Allocate aligned memory for `count` items of type T with the given alignment.
|
|
58
54
|
alloc_aligned : (fn(self : *(Self), comptime(T): Type, count: usize, alignment: usize) -> Result(?*(T), AllocError)),
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
* Reallocate memory to new_count items
|
|
62
|
-
*/
|
|
56
|
+
/// Reallocate memory to `new_count` items, preserving existing data.
|
|
63
57
|
realloc : (fn(forall(T : Type), self : *(Self), old_ptr : ?*(T), new_count : usize) -> Result(?*(T), AllocError)),
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
* Deallocate memory pointed to by ptr.
|
|
67
|
-
*/
|
|
59
|
+
/// Deallocate memory pointed to by `ptr`.
|
|
68
60
|
dealloc : (fn(forall(T : Type), self : *(Self), ptr : *(T)) -> Result(unit, AllocError))
|
|
69
61
|
);
|
|
70
62
|
|
|
63
|
+
/// Type-erased dynamic allocator wrapping any `CustomAllocator` implementation.
|
|
71
64
|
Allocator :: Dyn(CustomAllocator);
|
|
72
65
|
|
|
73
|
-
// Global Allocator
|
|
74
|
-
// We are using mimalloc if that's available
|
|
75
66
|
extern "Yo",
|
|
76
67
|
__yo_malloc :
|
|
77
68
|
fn(size: usize) -> ?*(void),
|
|
@@ -85,6 +76,7 @@ extern "Yo",
|
|
|
85
76
|
fn(alignment : usize, size : usize) -> ?*(void)
|
|
86
77
|
;
|
|
87
78
|
|
|
79
|
+
/// The process-wide global allocator (mimalloc by default, falls back to libc).
|
|
88
80
|
GlobalAllocator :: impl {
|
|
89
81
|
malloc :: __yo_malloc;
|
|
90
82
|
calloc :: __yo_calloc;
|
package/std/async.yo
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//! Async utilities for cooperative task scheduling.
|
|
2
|
+
|
|
3
|
+
/// Suspend the current async task, allowing other tasks to run on the event loop.
|
|
4
|
+
/// Implemented as an immediately-completing async block that forces a suspension point.
|
|
3
5
|
yield :: (fn(using(io : IO)) -> Impl(Future(unit)))(
|
|
4
6
|
io.async(()=> {
|
|
5
7
|
return ();
|