@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.
Files changed (164) hide show
  1. package/README.md +10 -1
  2. package/out/cjs/index.cjs +578 -572
  3. package/out/cjs/yo-cli.cjs +1413 -592
  4. package/out/esm/index.mjs +434 -428
  5. package/out/types/src/build-runner.d.ts +1 -1
  6. package/out/types/src/doc/builder.d.ts +21 -0
  7. package/out/types/src/doc/builder.test.d.ts +1 -0
  8. package/out/types/src/doc/extractor.d.ts +27 -0
  9. package/out/types/src/doc/extractor.test.d.ts +1 -0
  10. package/out/types/src/doc/model.d.ts +87 -0
  11. package/out/types/src/doc/render-html.d.ts +23 -0
  12. package/out/types/src/doc/render-html.test.d.ts +1 -0
  13. package/out/types/src/doc/render-json.d.ts +7 -0
  14. package/out/types/src/doc/render-json.test.d.ts +1 -0
  15. package/out/types/src/doc/render-markdown.d.ts +13 -0
  16. package/out/types/src/doc/render-markdown.test.d.ts +1 -0
  17. package/out/types/src/doc/sections.d.ts +7 -0
  18. package/out/types/src/doc/sections.test.d.ts +1 -0
  19. package/out/types/src/doc-command.d.ts +10 -0
  20. package/out/types/src/env.d.ts +1 -0
  21. package/out/types/src/evaluator/builtins/build.d.ts +17 -0
  22. package/out/types/src/evaluator/context.d.ts +1 -0
  23. package/out/types/src/expr.d.ts +2 -1
  24. package/out/types/src/token.d.ts +4 -0
  25. package/out/types/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +2 -1
  27. package/scripts/build-site.ts +461 -0
  28. package/std/alg/hash.yo +12 -24
  29. package/std/allocator.yo +21 -29
  30. package/std/async.yo +4 -2
  31. package/std/build.yo +188 -42
  32. package/std/cli/arg_parser.yo +37 -1
  33. package/std/collections/array_list.yo +8 -20
  34. package/std/collections/btree_map.yo +15 -20
  35. package/std/collections/deque.yo +13 -15
  36. package/std/collections/hash_map.yo +15 -54
  37. package/std/collections/hash_set.yo +14 -50
  38. package/std/collections/linked_list.yo +6 -23
  39. package/std/collections/priority_queue.yo +15 -17
  40. package/std/crypto/md5.yo +10 -9
  41. package/std/crypto/random.yo +14 -12
  42. package/std/crypto/sha256.yo +9 -8
  43. package/std/encoding/base64.yo +13 -15
  44. package/std/encoding/hex.yo +14 -10
  45. package/std/encoding/html.yo +14 -11
  46. package/std/encoding/html_char_utils.yo +14 -11
  47. package/std/encoding/html_entities.yo +7 -8
  48. package/std/encoding/json.yo +36 -19
  49. package/std/encoding/punycode.yo +21 -18
  50. package/std/encoding/toml.yo +23 -9
  51. package/std/encoding/utf16.yo +16 -9
  52. package/std/error.yo +10 -23
  53. package/std/fmt/display.yo +15 -17
  54. package/std/fmt/index.yo +6 -27
  55. package/std/fmt/to_string.yo +4 -10
  56. package/std/fmt/writer.yo +33 -34
  57. package/std/fs/dir.yo +37 -30
  58. package/std/fs/file.yo +77 -75
  59. package/std/fs/metadata.yo +25 -25
  60. package/std/fs/temp.yo +21 -27
  61. package/std/fs/types.yo +20 -23
  62. package/std/fs/walker.yo +26 -31
  63. package/std/gc.yo +5 -0
  64. package/std/glob/index.yo +3 -0
  65. package/std/http/client.yo +25 -11
  66. package/std/http/http.yo +20 -0
  67. package/std/http/index.yo +1 -0
  68. package/std/io/reader.yo +4 -8
  69. package/std/io/writer.yo +4 -7
  70. package/std/libc/assert.yo +2 -2
  71. package/std/libc/ctype.yo +1 -2
  72. package/std/libc/dirent.yo +1 -2
  73. package/std/libc/errno.yo +1 -2
  74. package/std/libc/fcntl.yo +2 -2
  75. package/std/libc/float.yo +1 -2
  76. package/std/libc/limits.yo +1 -2
  77. package/std/libc/math.yo +2 -0
  78. package/std/libc/signal.yo +1 -2
  79. package/std/libc/stdatomic.yo +1 -2
  80. package/std/libc/stdint.yo +4 -3
  81. package/std/libc/stdio.yo +2 -0
  82. package/std/libc/stdlib.yo +2 -0
  83. package/std/libc/string.yo +2 -0
  84. package/std/libc/sys/stat.yo +1 -2
  85. package/std/libc/time.yo +2 -2
  86. package/std/libc/unistd.yo +2 -0
  87. package/std/libc/wctype.yo +1 -2
  88. package/std/libc/windows.yo +2 -2
  89. package/std/log/index.yo +11 -26
  90. package/std/net/addr.yo +18 -11
  91. package/std/net/dns.yo +3 -2
  92. package/std/net/errors.yo +16 -2
  93. package/std/net/tcp.yo +25 -22
  94. package/std/net/udp.yo +14 -12
  95. package/std/os/env.yo +23 -18
  96. package/std/os/signal.yo +31 -19
  97. package/std/path.yo +23 -74
  98. package/std/prelude.yo +284 -113
  99. package/std/process.yo +23 -37
  100. package/std/regex/compiler.yo +3 -5
  101. package/std/regex/flags.yo +11 -11
  102. package/std/regex/index.yo +2 -13
  103. package/std/regex/match.yo +3 -5
  104. package/std/regex/node.yo +6 -6
  105. package/std/regex/parser.yo +2 -4
  106. package/std/regex/unicode.yo +5 -5
  107. package/std/regex/vm.yo +5 -5
  108. package/std/string/index.yo +2 -1
  109. package/std/string/rune.yo +25 -1
  110. package/std/string/string.yo +31 -19
  111. package/std/string/unicode.yo +14 -15
  112. package/std/sync/channel.yo +18 -28
  113. package/std/sync/cond.yo +4 -0
  114. package/std/sync/mutex.yo +4 -1
  115. package/std/sync/once.yo +17 -19
  116. package/std/sync/rwlock.yo +19 -22
  117. package/std/sync/waitgroup.yo +21 -23
  118. package/std/sys/advise.yo +4 -4
  119. package/std/sys/bufio/buf_reader.yo +19 -16
  120. package/std/sys/bufio/buf_writer.yo +14 -11
  121. package/std/sys/clock.yo +4 -4
  122. package/std/sys/constants.yo +5 -5
  123. package/std/sys/copy.yo +9 -8
  124. package/std/sys/dir.yo +9 -8
  125. package/std/sys/dns.yo +8 -8
  126. package/std/sys/errors.yo +35 -6
  127. package/std/sys/events.yo +3 -3
  128. package/std/sys/externs.yo +3 -3
  129. package/std/sys/fallocate.yo +4 -4
  130. package/std/sys/fcntl.yo +8 -6
  131. package/std/sys/file.yo +7 -8
  132. package/std/sys/future.yo +1 -3
  133. package/std/sys/iov.yo +4 -4
  134. package/std/sys/lock.yo +7 -7
  135. package/std/sys/mmap.yo +7 -8
  136. package/std/sys/path.yo +4 -7
  137. package/std/sys/perm.yo +8 -8
  138. package/std/sys/pipe.yo +9 -8
  139. package/std/sys/process.yo +8 -8
  140. package/std/sys/seek.yo +4 -4
  141. package/std/sys/signal.yo +4 -4
  142. package/std/sys/signals.yo +4 -4
  143. package/std/sys/socket.yo +4 -4
  144. package/std/sys/socketpair.yo +4 -4
  145. package/std/sys/sockinfo.yo +4 -4
  146. package/std/sys/statfs.yo +8 -8
  147. package/std/sys/statx.yo +4 -4
  148. package/std/sys/sysinfo.yo +4 -4
  149. package/std/sys/tcp.yo +8 -8
  150. package/std/sys/temp.yo +9 -8
  151. package/std/sys/time.yo +8 -8
  152. package/std/sys/timer.yo +7 -8
  153. package/std/sys/tty.yo +13 -10
  154. package/std/sys/udp.yo +8 -8
  155. package/std/sys/umask.yo +4 -4
  156. package/std/sys/unix.yo +5 -5
  157. package/std/testing/bench.yo +21 -10
  158. package/std/thread.yo +18 -9
  159. package/std/time/datetime.yo +12 -14
  160. package/std/time/duration.yo +12 -14
  161. package/std/time/instant.yo +13 -16
  162. package/std/time/sleep.yo +9 -8
  163. package/std/url/index.yo +3 -19
  164. 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.12",
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, "&amp;")
62
+ .replace(/</g, "&lt;")
63
+ .replace(/>/g, "&gt;")
64
+ .replace(/"/g, "&quot;");
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 &mdash; <a href="${GITHUB_REPO}">GitHub</a> &middot; <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
- * FNV-1a (Fowler-Noll-Vo) hash function
3
- * A fast, non-cryptographic hash function with good distribution
4
- *
5
- * Constants:
6
- * - FNV_OFFSET_BASIS: 14695981039346656037 (0xcbf29ce484222325)
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
- * Combine two hash values
31
- * Used for hashing composite types (tuples, structs, etc.)
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
- // Async yield - suspends current task and allows other tasks to run
2
- // Implemented as an immediately-completing async block that forces a suspension point
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 ();