@shd101wyy/yo 0.1.26 → 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.
Files changed (167) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +4 -4
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +34 -34
  3. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  4. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +26 -26
  5. package/.github/skills/yo-project-workflow/SKILL.md +6 -3
  6. package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
  7. package/.github/skills/yo-syntax/SKILL.md +7 -6
  8. package/.github/skills/yo-syntax/syntax-cheatsheet.md +73 -60
  9. package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
  10. package/README.md +10 -8
  11. package/out/cjs/index.cjs +456 -438
  12. package/out/cjs/yo-cli.cjs +576 -543
  13. package/out/cjs/yo-lsp.cjs +559 -532
  14. package/out/esm/index.mjs +281 -263
  15. package/out/types/src/formatter.d.ts +11 -0
  16. package/out/types/src/lsp/formatting.d.ts +2 -0
  17. package/out/types/src/tests/formatter.test.d.ts +1 -0
  18. package/out/types/tsconfig.tsbuildinfo +1 -1
  19. package/package.json +1 -1
  20. package/std/alg/hash.yo +13 -21
  21. package/std/allocator.yo +25 -40
  22. package/std/async.yo +3 -7
  23. package/std/build.yo +105 -151
  24. package/std/cli/arg_parser.yo +184 -169
  25. package/std/collections/array_list.yo +350 -314
  26. package/std/collections/btree_map.yo +142 -131
  27. package/std/collections/deque.yo +132 -128
  28. package/std/collections/hash_map.yo +542 -566
  29. package/std/collections/hash_set.yo +623 -687
  30. package/std/collections/linked_list.yo +275 -293
  31. package/std/collections/ordered_map.yo +113 -85
  32. package/std/collections/priority_queue.yo +73 -73
  33. package/std/crypto/md5.yo +191 -95
  34. package/std/crypto/random.yo +56 -64
  35. package/std/crypto/sha256.yo +151 -107
  36. package/std/encoding/base64.yo +87 -81
  37. package/std/encoding/hex.yo +43 -50
  38. package/std/encoding/html.yo +56 -81
  39. package/std/encoding/html_char_utils.yo +7 -13
  40. package/std/encoding/html_entities.yo +2248 -2253
  41. package/std/encoding/json.yo +316 -224
  42. package/std/encoding/punycode.yo +86 -116
  43. package/std/encoding/toml.yo +67 -66
  44. package/std/encoding/utf16.yo +37 -44
  45. package/std/env.yo +62 -91
  46. package/std/error.yo +7 -15
  47. package/std/fmt/display.yo +5 -9
  48. package/std/fmt/index.yo +8 -14
  49. package/std/fmt/to_string.yo +330 -315
  50. package/std/fmt/writer.yo +58 -87
  51. package/std/fs/dir.yo +83 -102
  52. package/std/fs/file.yo +147 -180
  53. package/std/fs/metadata.yo +45 -78
  54. package/std/fs/temp.yo +55 -65
  55. package/std/fs/types.yo +27 -40
  56. package/std/fs/walker.yo +53 -68
  57. package/std/gc.yo +5 -8
  58. package/std/glob.yo +30 -43
  59. package/std/http/client.yo +107 -120
  60. package/std/http/http.yo +106 -96
  61. package/std/http/index.yo +4 -6
  62. package/std/imm/list.yo +88 -93
  63. package/std/imm/map.yo +528 -464
  64. package/std/imm/set.yo +52 -57
  65. package/std/imm/sorted_map.yo +340 -286
  66. package/std/imm/sorted_set.yo +57 -63
  67. package/std/imm/string.yo +404 -345
  68. package/std/imm/vec.yo +173 -181
  69. package/std/io/reader.yo +3 -6
  70. package/std/io/writer.yo +4 -8
  71. package/std/libc/assert.yo +5 -9
  72. package/std/libc/ctype.yo +32 -22
  73. package/std/libc/dirent.yo +26 -25
  74. package/std/libc/errno.yo +164 -90
  75. package/std/libc/fcntl.yo +52 -45
  76. package/std/libc/float.yo +66 -44
  77. package/std/libc/limits.yo +42 -33
  78. package/std/libc/math.yo +53 -82
  79. package/std/libc/signal.yo +72 -47
  80. package/std/libc/stdatomic.yo +217 -188
  81. package/std/libc/stdint.yo +5 -29
  82. package/std/libc/stdio.yo +5 -29
  83. package/std/libc/stdlib.yo +32 -39
  84. package/std/libc/string.yo +5 -23
  85. package/std/libc/sys/stat.yo +58 -56
  86. package/std/libc/time.yo +5 -19
  87. package/std/libc/unistd.yo +5 -20
  88. package/std/libc/wctype.yo +6 -9
  89. package/std/libc/windows.yo +26 -30
  90. package/std/log.yo +41 -55
  91. package/std/net/addr.yo +102 -97
  92. package/std/net/dns.yo +27 -28
  93. package/std/net/errors.yo +50 -49
  94. package/std/net/tcp.yo +113 -124
  95. package/std/net/udp.yo +55 -66
  96. package/std/os/env.yo +35 -33
  97. package/std/os/signal.yo +15 -25
  98. package/std/path.yo +276 -311
  99. package/std/prelude.yo +6304 -4315
  100. package/std/process/command.yo +87 -103
  101. package/std/process/index.yo +12 -31
  102. package/std/regex/compiler.yo +196 -95
  103. package/std/regex/flags.yo +58 -39
  104. package/std/regex/index.yo +157 -173
  105. package/std/regex/match.yo +20 -31
  106. package/std/regex/node.yo +134 -152
  107. package/std/regex/parser.yo +283 -259
  108. package/std/regex/unicode.yo +172 -202
  109. package/std/regex/vm.yo +155 -171
  110. package/std/string/index.yo +5 -7
  111. package/std/string/rune.yo +45 -55
  112. package/std/string/string.yo +937 -964
  113. package/std/string/string_builder.yo +94 -104
  114. package/std/string/unicode.yo +46 -64
  115. package/std/sync/channel.yo +72 -73
  116. package/std/sync/cond.yo +31 -36
  117. package/std/sync/mutex.yo +30 -32
  118. package/std/sync/once.yo +13 -16
  119. package/std/sync/rwlock.yo +26 -31
  120. package/std/sync/waitgroup.yo +20 -25
  121. package/std/sys/advise.yo +16 -24
  122. package/std/sys/bufio/buf_reader.yo +77 -93
  123. package/std/sys/bufio/buf_writer.yo +52 -65
  124. package/std/sys/clock.yo +4 -9
  125. package/std/sys/constants.yo +77 -61
  126. package/std/sys/copy.yo +4 -10
  127. package/std/sys/dir.yo +26 -43
  128. package/std/sys/dns.yo +41 -61
  129. package/std/sys/errors.yo +95 -103
  130. package/std/sys/events.yo +45 -57
  131. package/std/sys/externs.yo +319 -267
  132. package/std/sys/fallocate.yo +7 -11
  133. package/std/sys/fcntl.yo +14 -22
  134. package/std/sys/file.yo +26 -40
  135. package/std/sys/future.yo +5 -8
  136. package/std/sys/iov.yo +12 -25
  137. package/std/sys/lock.yo +12 -13
  138. package/std/sys/mmap.yo +38 -43
  139. package/std/sys/path.yo +3 -8
  140. package/std/sys/perm.yo +7 -21
  141. package/std/sys/pipe.yo +5 -12
  142. package/std/sys/process.yo +23 -29
  143. package/std/sys/seek.yo +10 -12
  144. package/std/sys/signal.yo +7 -13
  145. package/std/sys/signals.yo +52 -35
  146. package/std/sys/socket.yo +63 -58
  147. package/std/sys/socketpair.yo +3 -6
  148. package/std/sys/sockinfo.yo +11 -20
  149. package/std/sys/statfs.yo +11 -34
  150. package/std/sys/statx.yo +25 -52
  151. package/std/sys/sysinfo.yo +15 -20
  152. package/std/sys/tcp.yo +62 -92
  153. package/std/sys/temp.yo +5 -9
  154. package/std/sys/time.yo +5 -15
  155. package/std/sys/timer.yo +6 -11
  156. package/std/sys/tty.yo +10 -18
  157. package/std/sys/udp.yo +22 -39
  158. package/std/sys/umask.yo +3 -6
  159. package/std/sys/unix.yo +33 -52
  160. package/std/testing/bench.yo +49 -52
  161. package/std/thread.yo +10 -15
  162. package/std/time/datetime.yo +105 -89
  163. package/std/time/duration.yo +43 -56
  164. package/std/time/instant.yo +13 -18
  165. package/std/time/sleep.yo +5 -9
  166. package/std/url/index.yo +184 -209
  167. package/std/worker.yo +6 -10
@@ -13,7 +13,7 @@ These are baseline syntax rules for portable Yo code.
13
13
  ## Common declaration forms
14
14
 
15
15
  ```rust
16
- { println } :: import "std/fmt";
16
+ { println } :: import("std/fmt");
17
17
 
18
18
  app_name :: "yo-demo";
19
19
 
@@ -23,21 +23,22 @@ main :: (fn() -> unit)({
23
23
  println(message);
24
24
  });
25
25
 
26
- export main;
26
+ export(main);
27
27
  ```
28
28
 
29
29
  - Top-level binding: `name :: expr;`
30
30
  - Local binding: `name := expr;`
31
31
  - Typed binding: `(name : Type) = expr;`
32
32
  - Function definition: `name :: (fn(args...) -> ReturnType)(body);`
33
+ - Export: `export(name);`
33
34
 
34
35
  ## Blocks and expressions
35
36
 
36
- | Goal | Write | Avoid |
37
- | ----------------- | -------------------------- | -------------------------- |
38
- | Single expression | `cond(...)` | `{ cond(...) }` |
39
- | Begin block | `{ x := i32(1); x }` | `{ x := i32(1), x }` |
40
- | Struct literal | `{ name: "yo", ok: true }` | `{ name: "yo"; ok: true }` |
37
+ | Goal | Write | Avoid |
38
+ | ----------------- | ---------------------------- | ---------------------------- |
39
+ | Single expression | `cond(...)` | `{ cond(...) }` |
40
+ | Begin block | `{ x := i32(1); x }` | `{ x := i32(1), x }` |
41
+ | Struct literal | `{ name : "yo", ok : true }` | `{ name : "yo"; ok : true }` |
41
42
 
42
43
  ```rust
43
44
  result := cond(
@@ -53,6 +54,8 @@ total := {
53
54
 
54
55
  Remember: `{ expr }` without semicolons is a struct literal, not a block. The parser now detects this mistake and emits a clear error if the single expression is not a valid struct field.
55
56
 
57
+ In struct literals, keep spaces around `:` and parenthesize infix field values: `{ x : (1 + 2), y : 3 }`, not `{ x: 1 + 2, y: 3 }`.
58
+
56
59
  ## Control flow
57
60
 
58
61
  ```rust
@@ -74,6 +77,8 @@ if(done, println("done"), println("pending"));
74
77
  - Always write `cond(...)`, never bare `cond ...`
75
78
  - Always write `match(...)`, never bare `match ...`
76
79
  - `if(a, b)` and `if(a, b, c)` are macro forms over `cond`
80
+ - Write `return(value)` or `return()`; `return value` is invalid.
81
+ - Write `escape(value)` or `escape()`; `escape value` is invalid.
77
82
 
78
83
  ## String types
79
84
 
@@ -101,10 +106,18 @@ flag := ((a > b) && (b > c));
101
106
  masked := ((A | B) | C);
102
107
  ```
103
108
 
104
- - Prefer parenthesized calls: `func(arg1, arg2)`
105
- - `func (a, b)` is a different parse shape than `func(a, b)`
109
+ - Calls require immediate parentheses: `func(arg1, arg2)`
110
+ - `func arg1, arg2` and `func (arg1, arg2)` are invalid
106
111
  - Yo has no operator precedence; fully parenthesize binary expressions
107
- - **All unary operators (`!`, `&`, `-`, `~`) greedily consume everything that follows, including comma-separated args.** `func(&s, a, b)` is parsed as `func(&(s, a, b))` — ONE tuple argument! Preferred fix: parenthesize the operand: `func(&(s), a, b)`. The outer-parens form `func((&s), a, b)` also works. Either is fine; the operand-parens form `&(x)` matches how the parser thinks about it.
112
+ - Preserve grouping around infix expressions on operator RHS positions: `true => (x / y)`, `value := (x + y)`, `(ptr &+ 1).*`
113
+ - Line breaks can disambiguate operator chains; keep line-leading operators like `(4\n| 5\n| 6)` and newlines after `:` before a lambda unless you add equivalent grouping
114
+ - When an operator ends a line, indent its RHS one level as a continuation: `(given(x) : T) =\n (v) -> { ... }`
115
+ - Prefix operators (`!`, `&`, `-`, `~`) require parenthesized operands: `func(&(s), a, b)`, `!(ready)`, `-(value)`.
116
+ - Tight special forms also require immediate parentheses: `#(expr)`, `?*(u8)`, `T <: !(Runtime)`
117
+ - Dynamic field access with unquote must keep grouping after the dot: `value.(#(field_expr))`, not `value.#(field_expr)`.
118
+ - Unquote splicing is the tight operator `...#(exprs)`; do not insert a space between `...` and `#`.
119
+ - Canonical pointer dereference is `ptr.*`; formatter should canonicalize legacy `ptr.(*)` to `ptr.*`.
120
+ - Keep single-line array and tuple literals compact during formatting: `[1, 2, 3]`, `(1, 2, 3)`.
108
121
  - Parenthesize other unary operands too: `!(ready)`, `-(value)`
109
122
  - **`!x && y` is parsed as `!(x && y)`**, not `(!x) && y`. Prefix `!` greedily consumes the full right-hand expression. To get `(!x) && y`, write `((!x) && y)` with explicit inner parens.
110
123
  - **Nested `&&` / `||` in a single compound condition causes "Ambiguous operator precedence"** even with explicit parentheses: `((A && B) && (C && D))` on one line triggers the error. Fix: extract sub-conditions into named booleans first: `_c1 := (A && B); _c2 := (C && D); if((_c1 && _c2), ...)`.
@@ -169,7 +182,7 @@ safe_divide :: (fn(x : i32, y : i32, using(raise : Raise)) -> i32)(
169
182
 
170
183
  caller :: (fn() -> i32)({
171
184
  (given(raise) : Raise) = (fn(msg : String) -> i32)({
172
- return i32(0);
185
+ return(i32(0));
173
186
  });
174
187
 
175
188
  safe_divide(i32(10), i32(0))
@@ -189,9 +202,9 @@ caller :: (fn() -> i32)({
189
202
  result := closure(i32(5));
190
203
 
191
204
  transform :: (fn(list : ArrayList(i32), f : Impl(Fn(x : i32) -> i32)) -> unit)({
192
- for list.iter(), (ptr) => {
205
+ for(list.iter(), (ptr) => {
193
206
  ptr.* = f(ptr.*);
194
- };
207
+ });
195
208
  });
196
209
  ```
197
210
 
@@ -203,15 +216,15 @@ transform :: (fn(list : ArrayList(i32), f : Impl(Fn(x : i32) -> i32)) -> unit)({
203
216
  ## Imports and modules
204
217
 
205
218
  ```rust
206
- { Parser } :: import "./parser.yo";
207
- parser_module :: import "./parser.yo";
219
+ { Parser } :: import("./parser.yo");
220
+ parser_module :: import("./parser.yo");
208
221
 
209
- open import "std/string";
210
- { ArrayList } :: import "std/collections/array_list";
222
+ open(import("std/string"));
223
+ { ArrayList } :: import("std/collections/array_list");
211
224
  ```
212
225
 
213
226
  - Use relative imports for nearby `.yo` files
214
- - Use `open import "std/module"` for standard-library modules you want fully in scope
227
+ - Use `open(import("std/module"))` for standard-library modules you want fully in scope
215
228
  - Do not write `import "./file.yo" as name`
216
229
  - Do not import `std/prelude`
217
230
 
@@ -273,17 +286,17 @@ show :: (fn(forall(T : Type), value : T, where(T <: ToString)) -> unit)(
273
286
 
274
287
  ```rust
275
288
  main :: (fn() -> unit)(());
276
- export main;
289
+ export(main);
277
290
 
278
- export
291
+ export(
279
292
  helper,
280
293
  Config
281
- ;
294
+ );
282
295
  ```
283
296
 
284
- - `export name;` exports a single binding
297
+ - `export(name);` exports a single binding
285
298
  - Block form exports multiple bindings separated by commas
286
- - Every executable needs `export main;`
299
+ - Every executable needs `export(main);`
287
300
 
288
301
  ## Static and dynamic dispatch types
289
302
 
@@ -321,15 +334,15 @@ factorial :: (fn(n : i32) -> i32)(
321
334
  )
322
335
  );
323
336
 
324
- // Runtime infinite loop — `while cond` is ALWAYS runtime
325
- while true, {
337
+ // Runtime infinite loop — `while(cond, body)` is ALWAYS runtime
338
+ while(true, {
326
339
  work();
327
- };
340
+ });
328
341
 
329
342
  // Compile-time loop unrolling — requires comptime() modifier
330
- while comptime(i < 10), {
343
+ while(comptime((i < 10)), {
331
344
  // body evaluated/unrolled at compile time
332
- };
345
+ });
333
346
 
334
347
  // for loop — 2-arg prelude macro; first arg MUST be an iterator (has .next()):
335
348
  for(list.iter(), x => { // ArrayList, array → call .iter() first
@@ -346,8 +359,8 @@ for(list.iter(), (ptr) => { // ptr is a mutable reference to each element
346
359
  ```
347
360
 
348
361
  - Use `recur(...)` for self-recursion
349
- - `while cond` is **always a runtime loop** — use this for open-ended loops (e.g., server accept loops, event loops)
350
- - `while comptime(cond)` explicitly unrolls at compile time — `cond` must be a compile-time-known value
362
+ - `while(cond, body)` is **always a runtime loop** — use this for open-ended loops (e.g., server accept loops, event loops)
363
+ - `while(comptime(cond), body)` explicitly unrolls at compile time — `cond` must be a compile-time-known value
351
364
  - Using a comptime-only (`::`) variable in a bare `while` condition without `comptime()` is a **compile error** (would be an infinite loop at runtime)
352
365
  - **`for(arr, item => { body })`** — correct 2-arg prelude macro form. The `item => { body }` is an anonymous closure.
353
366
  - **Do NOT use `for(x, arr, { body })`** — this older 3-arg form is an evaluator-internal representation, not valid top-level Yo syntax. (The self-hosted evaluator currently only understands the 3-arg form in its internal for-loop handler; track issue: `issues/eval-for-loop-3arg-vs-2arg.md`)
@@ -355,19 +368,19 @@ for(list.iter(), (ptr) => { // ptr is a mutable reference to each element
355
368
  ## Return and branch safety
356
369
 
357
370
  ```rust
358
- // WRONG — return consumes the comma, capturing the next match branch:
371
+ // WRONG — paren-less return is invalid:
359
372
  match(opt,
360
- .Some(v) => return v, // parsed as return(v, .None => ...)
373
+ .Some(v) => return v,
361
374
  .None => default_value()
362
375
  );
363
376
 
364
- // CORRECT — begin blocks isolate return from the comma:
377
+ // CORRECT — explicit return calls in begin blocks:
365
378
  match(opt,
366
379
  .Some(v) => {
367
- return v;
380
+ return(v);
368
381
  },
369
382
  .None => {
370
- return default_value();
383
+ return(default_value());
371
384
  }
372
385
  );
373
386
 
@@ -380,11 +393,11 @@ get_value :: (fn(opt : Option(i32)) -> i32)(
380
393
  );
381
394
  ```
382
395
 
383
- - `return expr1, expr2` parses as a single function call: `return(expr1, expr2)`
396
+ - `return expr` is invalid; write `return(expr)` or `return()` for unit
384
397
  - In `cond` or `match` branches, **always use begin blocks** when you need `return`
385
- - `return` must be the **last expression** in a begin block — dead code after `return` is rejected. Do NOT write `{ return x; fallback_val }`. Write `{ return x; }` only.
398
+ - `return(...)` must be the **last expression** in a begin block — dead code after `return(...)` is rejected. Do NOT write `{ return(x); fallback_val }`. Write `{ return(x); }` only.
386
399
  - If the whole function is one expression, prefer expression-bodied style and skip `return` entirely
387
- - The same trap applies to any function call without parens in match branches
400
+ - The same rule applies to all calls in match branches: use immediate `(...)`
388
401
 
389
402
  ## String concatenation pitfall
390
403
 
@@ -406,43 +419,43 @@ content := String.from("line1\nline2\n");
406
419
  ## Iterator and for loop
407
420
 
408
421
  ```rust
409
- { ArrayList } :: import "std/collections/array_list";
422
+ { ArrayList } :: import("std/collections/array_list");
410
423
 
411
424
  list := ArrayList(i32).new();
412
425
  list.push(i32(10));
413
426
  list.push(i32(20));
414
427
 
415
- for list.iter(), (ptr) => {
428
+ for(list.iter(), (ptr) => {
416
429
  println(ptr.*);
417
- };
430
+ });
418
431
 
419
- for list.into_iter(), (value) => {
432
+ for(list.into_iter(), (value) => {
420
433
  println(value);
421
- };
434
+ });
422
435
  ```
423
436
 
424
- - `for collection, (variable) => { body }` iterates via the `Iterator` trait
437
+ - `for(collection, (variable) => { body })` iterates via the `Iterator` trait
425
438
  - `.iter()` borrows the collection and yields pointers
426
439
  - `.into_iter()` takes ownership and yields values
427
440
 
428
441
  ## Testing
429
442
 
430
443
  ```rust
431
- test "Addition works", {
444
+ test("Addition works", {
432
445
  assert(((i32(1) + i32(1)) == i32(2)), "1+1 should be 2");
433
- };
446
+ });
434
447
 
435
- test "Compile-time check", {
448
+ test("Compile-time check", {
436
449
  comptime_assert((2 + 2) == 4);
437
450
  comptime_expect_error({ x :: (1 / 0); });
438
- };
451
+ });
439
452
 
440
- test "Async test", {
453
+ test("Async test", {
441
454
  io.await(yield());
442
- };
455
+ });
443
456
  ```
444
457
 
445
- - `test "description", { body }` defines a test — `io : IO` is automatically available
458
+ - `test("description", { body })` defines a test — `io : IO` is automatically available
446
459
  - All tests can use `io.async(...)`, `io.await(...)`, etc. without a `using` clause
447
460
  - `assert(condition, "message")` — runtime assertion (always include a message)
448
461
  - `comptime_assert(condition)` — compile-time assertion
@@ -671,7 +684,7 @@ if((!cond), { do_thing(); });
671
684
 
672
685
  ### `escape` requires a nested-function context
673
686
 
674
- `escape value` exits the **enclosing function** — the nearest `fn(...)` that
687
+ `escape(value)` exits the **enclosing function** — the nearest `fn(...)` that
675
688
  wraps the current code. It requires that the code is inside a nested function
676
689
  (e.g., a closure or `given` handler lambda), NOT at the top level of a
677
690
  standalone function definition.
@@ -679,20 +692,20 @@ standalone function definition.
679
692
  ```rust
680
693
  // CORRECT — escape inside a given handler lambda (lambda has enclosing fn):
681
694
  given(exn) := Exception(throw: ((err) -> {
682
- escape result // exits the outer function that contains this given()
695
+ escape(result); // exits the outer function that contains this given()
683
696
  }));
684
697
  do_something(using(exn));
685
698
 
686
699
  // CORRECT — escape inside a closure passed as argument:
687
700
  result := match(opt, .Some(x) => x, .None => {
688
701
  // This is NOT a nested function — use return:
689
- // WRONG: escape default_val // ERROR: no enclosing fn
690
- return default_val // CORRECT: return exits the enclosing fn directly
702
+ // WRONG: escape(default_val) // ERROR: no enclosing fn
703
+ return(default_val); // CORRECT: return exits the enclosing fn directly
691
704
  });
692
705
 
693
706
  // WRONG — escape inside a match arm (not a nested fn):
694
707
  match(opt,
695
- .Some(x) => { escape x } // ERROR: "can only be used inside a function that has an enclosing function"
708
+ .Some(x) => { escape(x); } // ERROR: "can only be used inside a function that has an enclosing function"
696
709
  );
697
710
  ```
698
711
 
@@ -923,16 +936,16 @@ if (((is_tuple_type(ty) || is_struct_type(ty)) || is_union_type(ty)), ...)
923
936
 
924
937
  ### Duplicate imports from the same path must be merged
925
938
 
926
- Having two `:: import "path"` lines importing from the same file causes a compile error.
939
+ Having two `:: import("path")` lines importing from the same file causes a compile error.
927
940
  Always merge them into a single destructuring import:
928
941
 
929
942
  ```rust
930
943
  // ❌ Two imports from the same path
931
- { Foo } :: import "../../mod.yo";
932
- { Bar } :: import "../../mod.yo";
944
+ { Foo } :: import("../../mod.yo");
945
+ { Bar } :: import("../../mod.yo");
933
946
 
934
947
  // ✅ Merged
935
- { Foo, Bar } :: import "../../mod.yo";
948
+ { Foo, Bar } :: import("../../mod.yo");
936
949
  ```
937
950
 
938
951
  ### Implicit (`using`) parameters cannot be used with `:=` assignment
@@ -16,7 +16,7 @@ Export C-compatible functions that operate on linear memory:
16
16
 
17
17
  ```rust
18
18
  // src/wasm_api.yo
19
- open import "std/string";
19
+ open(import("std/string"));
20
20
 
21
21
  // Allocate WASM memory for the caller
22
22
  wasm_alloc :: (fn(size : usize) -> *(u8))(
@@ -89,7 +89,7 @@ The `Executable` struct accepts: `name`, `root`, `target`, `optimize`, `allocato
89
89
  Emscripten-specific flags go in `add_c_flags(...)` after creating the step.
90
90
 
91
91
  ```rust
92
- build :: import "std/build";
92
+ build :: import("std/build");
93
93
 
94
94
  wasm_api :: build.executable({
95
95
  name: "my_lib_wasm_api",
@@ -242,7 +242,7 @@ cd npm && node -e "const m = require('.'); m.createRenderer().render('hello').th
242
242
  - **Memory leaks**: Always `_wasm_free` every `_wasm_alloc` on the JavaScript side.
243
243
  - **String encoding**: WASM only sees bytes — use `TextEncoder`/`TextDecoder` for UTF-8.
244
244
  - **Errno differences**: WASI errno values differ from POSIX. Use `std/libc/errno` constants.
245
- - **No `main` needed**: Library WASM modules don't need `main` or `export main;` — just export the API functions.
245
+ - **No `main` needed**: Library WASM modules don't need `main` or `export(main);` — just export the API functions.
246
246
  - **Emscripten environment**: Set `-sENVIRONMENT='web,node'` to support both contexts, or `'node'` for Node.js only.
247
247
  - **Module initialization is async**: Emscripten's `createModule()` returns a Promise. Initialize once and reuse.
248
248
  - **WASM memory growth**: Always use `-sALLOW_MEMORY_GROWTH=1` for dynamic allocations.
package/README.md CHANGED
@@ -202,14 +202,14 @@ my-project/
202
202
 
203
203
  `src/main.yo`:
204
204
 
205
- ```typescript
206
- { println } :: import "std/fmt";
205
+ ```rust
206
+ { println } :: import("std/fmt");
207
207
 
208
208
  main :: (fn() -> unit)({
209
209
  println("Hello, world!");
210
210
  });
211
211
 
212
- export main;
212
+ export(main);
213
213
  ```
214
214
 
215
215
  Common build commands:
@@ -220,6 +220,8 @@ $ yo build run # Build and run the executable
220
220
  $ yo build test # Run tests
221
221
  $ yo build --list-steps # List available build steps
222
222
  $ yo build doc # Generate HTML documentation
223
+ $ yo fmt # Format Yo source files
224
+ $ yo fmt --check # Check formatting without writing changes
223
225
  ```
224
226
 
225
227
  ## Prelude
@@ -254,15 +256,15 @@ Check the [./tests](./tests/) and [./std](./std/) folders for more code examples
254
256
 
255
257
  ### Hello World
256
258
 
257
- ```typescript
259
+ ```rust
258
260
  // main.yo
259
- { println } :: import "std/fmt";
261
+ { println } :: import("std/fmt");
260
262
 
261
- main :: (fn() -> unit) {
263
+ main :: (fn() -> unit)({
262
264
  println("Hello, world!");
263
- };
265
+ });
264
266
 
265
- export main;
267
+ export(main);
266
268
 
267
269
  // $ yo compile main.yo --release -o main
268
270
  // $ ./main