@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.
Files changed (194) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +4 -4
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +40 -40
  3. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  4. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +30 -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 +78 -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 +583 -567
  12. package/out/cjs/yo-cli.cjs +664 -632
  13. package/out/cjs/yo-lsp.cjs +510 -485
  14. package/out/esm/index.mjs +538 -522
  15. package/out/types/src/codegen/codegen-c.d.ts +2 -2
  16. package/out/types/src/codegen/functions/collection.d.ts +2 -2
  17. package/out/types/src/codegen/functions/context.d.ts +3 -2
  18. package/out/types/src/codegen/types/collection.d.ts +2 -2
  19. package/out/types/src/codegen/utils/index.d.ts +3 -1
  20. package/out/types/src/doc/builder.d.ts +2 -2
  21. package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
  22. package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
  23. package/out/types/src/evaluator/context.d.ts +8 -9
  24. package/out/types/src/evaluator/index.d.ts +3 -3
  25. package/out/types/src/evaluator/types/record.d.ts +14 -0
  26. package/out/types/src/evaluator/types/validation.d.ts +2 -2
  27. package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
  28. package/out/types/src/evaluator/values/impl.d.ts +1 -1
  29. package/out/types/src/expr.d.ts +1 -4
  30. package/out/types/src/formatter.d.ts +11 -0
  31. package/out/types/src/function-value.d.ts +1 -1
  32. package/out/types/src/lsp/document-manager.d.ts +1 -1
  33. package/out/types/src/lsp/formatting.d.ts +2 -0
  34. package/out/types/src/module-manager.d.ts +3 -3
  35. package/out/types/src/tests/formatter.test.d.ts +1 -0
  36. package/out/types/src/types/creators.d.ts +3 -4
  37. package/out/types/src/types/definitions.d.ts +8 -19
  38. package/out/types/src/types/guards.d.ts +3 -3
  39. package/out/types/src/types/tags.d.ts +0 -1
  40. package/out/types/src/types/utils.d.ts +1 -1
  41. package/out/types/src/value-tag.d.ts +0 -1
  42. package/out/types/src/value.d.ts +6 -13
  43. package/out/types/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +1 -1
  45. package/std/alg/hash.yo +13 -21
  46. package/std/allocator.yo +25 -40
  47. package/std/async.yo +3 -7
  48. package/std/build.yo +105 -151
  49. package/std/cli/arg_parser.yo +184 -169
  50. package/std/collections/array_list.yo +350 -314
  51. package/std/collections/btree_map.yo +142 -131
  52. package/std/collections/deque.yo +132 -128
  53. package/std/collections/hash_map.yo +542 -566
  54. package/std/collections/hash_set.yo +623 -687
  55. package/std/collections/linked_list.yo +275 -293
  56. package/std/collections/ordered_map.yo +113 -85
  57. package/std/collections/priority_queue.yo +73 -73
  58. package/std/crypto/md5.yo +191 -95
  59. package/std/crypto/random.yo +56 -64
  60. package/std/crypto/sha256.yo +151 -107
  61. package/std/encoding/base64.yo +87 -81
  62. package/std/encoding/hex.yo +43 -50
  63. package/std/encoding/html.yo +56 -81
  64. package/std/encoding/html_char_utils.yo +7 -13
  65. package/std/encoding/html_entities.yo +2248 -2253
  66. package/std/encoding/json.yo +316 -224
  67. package/std/encoding/punycode.yo +86 -116
  68. package/std/encoding/toml.yo +67 -66
  69. package/std/encoding/utf16.yo +37 -44
  70. package/std/env.yo +62 -91
  71. package/std/error.yo +12 -20
  72. package/std/fmt/display.yo +5 -9
  73. package/std/fmt/index.yo +8 -14
  74. package/std/fmt/to_string.yo +330 -315
  75. package/std/fmt/writer.yo +58 -87
  76. package/std/fs/dir.yo +83 -102
  77. package/std/fs/file.yo +147 -180
  78. package/std/fs/metadata.yo +45 -78
  79. package/std/fs/temp.yo +55 -65
  80. package/std/fs/types.yo +27 -40
  81. package/std/fs/walker.yo +53 -68
  82. package/std/gc.yo +5 -8
  83. package/std/glob.yo +30 -43
  84. package/std/http/client.yo +107 -120
  85. package/std/http/http.yo +106 -96
  86. package/std/http/index.yo +4 -6
  87. package/std/imm/list.yo +88 -93
  88. package/std/imm/map.yo +528 -464
  89. package/std/imm/set.yo +52 -57
  90. package/std/imm/sorted_map.yo +340 -286
  91. package/std/imm/sorted_set.yo +57 -63
  92. package/std/imm/string.yo +404 -345
  93. package/std/imm/vec.yo +173 -181
  94. package/std/io/reader.yo +3 -6
  95. package/std/io/writer.yo +4 -8
  96. package/std/libc/assert.yo +5 -9
  97. package/std/libc/ctype.yo +32 -22
  98. package/std/libc/dirent.yo +26 -25
  99. package/std/libc/errno.yo +164 -90
  100. package/std/libc/fcntl.yo +52 -45
  101. package/std/libc/float.yo +66 -44
  102. package/std/libc/limits.yo +42 -33
  103. package/std/libc/math.yo +53 -82
  104. package/std/libc/signal.yo +72 -47
  105. package/std/libc/stdatomic.yo +217 -188
  106. package/std/libc/stdint.yo +5 -29
  107. package/std/libc/stdio.yo +5 -29
  108. package/std/libc/stdlib.yo +32 -39
  109. package/std/libc/string.yo +5 -23
  110. package/std/libc/sys/stat.yo +58 -56
  111. package/std/libc/time.yo +5 -19
  112. package/std/libc/unistd.yo +5 -20
  113. package/std/libc/wctype.yo +6 -9
  114. package/std/libc/windows.yo +26 -30
  115. package/std/log.yo +41 -55
  116. package/std/net/addr.yo +102 -97
  117. package/std/net/dns.yo +27 -28
  118. package/std/net/errors.yo +50 -49
  119. package/std/net/tcp.yo +113 -124
  120. package/std/net/udp.yo +55 -66
  121. package/std/os/env.yo +35 -33
  122. package/std/os/signal.yo +15 -25
  123. package/std/path.yo +276 -311
  124. package/std/prelude.yo +6316 -4333
  125. package/std/process/command.yo +87 -103
  126. package/std/process/index.yo +12 -31
  127. package/std/regex/compiler.yo +196 -95
  128. package/std/regex/flags.yo +58 -39
  129. package/std/regex/index.yo +157 -173
  130. package/std/regex/match.yo +20 -31
  131. package/std/regex/node.yo +134 -152
  132. package/std/regex/parser.yo +283 -259
  133. package/std/regex/unicode.yo +172 -202
  134. package/std/regex/vm.yo +155 -171
  135. package/std/string/index.yo +5 -7
  136. package/std/string/rune.yo +45 -55
  137. package/std/string/string.yo +937 -964
  138. package/std/string/string_builder.yo +94 -104
  139. package/std/string/unicode.yo +46 -64
  140. package/std/sync/channel.yo +72 -73
  141. package/std/sync/cond.yo +31 -36
  142. package/std/sync/mutex.yo +30 -32
  143. package/std/sync/once.yo +13 -16
  144. package/std/sync/rwlock.yo +26 -31
  145. package/std/sync/waitgroup.yo +20 -25
  146. package/std/sys/advise.yo +16 -24
  147. package/std/sys/bufio/buf_reader.yo +77 -93
  148. package/std/sys/bufio/buf_writer.yo +52 -65
  149. package/std/sys/clock.yo +4 -9
  150. package/std/sys/constants.yo +77 -61
  151. package/std/sys/copy.yo +4 -10
  152. package/std/sys/dir.yo +26 -43
  153. package/std/sys/dns.yo +41 -61
  154. package/std/sys/errors.yo +95 -103
  155. package/std/sys/events.yo +45 -57
  156. package/std/sys/externs.yo +319 -267
  157. package/std/sys/fallocate.yo +7 -11
  158. package/std/sys/fcntl.yo +14 -22
  159. package/std/sys/file.yo +26 -40
  160. package/std/sys/future.yo +5 -8
  161. package/std/sys/iov.yo +12 -25
  162. package/std/sys/lock.yo +12 -13
  163. package/std/sys/mmap.yo +38 -43
  164. package/std/sys/path.yo +3 -8
  165. package/std/sys/perm.yo +7 -21
  166. package/std/sys/pipe.yo +5 -12
  167. package/std/sys/process.yo +23 -29
  168. package/std/sys/seek.yo +10 -12
  169. package/std/sys/signal.yo +7 -13
  170. package/std/sys/signals.yo +52 -35
  171. package/std/sys/socket.yo +63 -58
  172. package/std/sys/socketpair.yo +3 -6
  173. package/std/sys/sockinfo.yo +11 -20
  174. package/std/sys/statfs.yo +11 -34
  175. package/std/sys/statx.yo +25 -52
  176. package/std/sys/sysinfo.yo +15 -20
  177. package/std/sys/tcp.yo +62 -92
  178. package/std/sys/temp.yo +5 -9
  179. package/std/sys/time.yo +5 -15
  180. package/std/sys/timer.yo +6 -11
  181. package/std/sys/tty.yo +10 -18
  182. package/std/sys/udp.yo +22 -39
  183. package/std/sys/umask.yo +3 -6
  184. package/std/sys/unix.yo +33 -52
  185. package/std/testing/bench.yo +49 -52
  186. package/std/thread.yo +10 -15
  187. package/std/time/datetime.yo +105 -89
  188. package/std/time/duration.yo +43 -56
  189. package/std/time/instant.yo +13 -18
  190. package/std/time/sleep.yo +5 -9
  191. package/std/url/index.yo +184 -209
  192. package/std/worker.yo +6 -10
  193. package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
  194. package/out/types/src/evaluator/types/module.d.ts +0 -19
@@ -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), ...)`.
@@ -129,6 +142,11 @@ impl(Counter,
129
142
  - No space between a function type and its body: `(fn(...) -> T)(...)`
130
143
  - Use `Self` in method signatures and in type definitions for recursive references (the type name is not available during its own definition)
131
144
  - `Self` also works inside generic type constructors — it refers to the current instantiation (e.g., `Tree(T)` inside `Tree`). Use `recur(args)` only when type arguments differ from the current instantiation.
145
+ - Use `struct(...)` for record and effect-record types. The legacy `module(...)`,
146
+ `Module`, and `SelfModule` syntax has been removed; imported files are
147
+ represented as namespace structs, and recursive references use normal `Self`.
148
+ - Bare `Module` is not a type alias. Use `Type` for comptime type values; type
149
+ reflection reports source-module namespaces as `TypeInfo.Struct(...)`.
132
150
  - Wrap `fn` types in parentheses when they appear after `:`
133
151
  - **Forward references between methods in the same `impl` block are supported.** A method defined later in the block can be called by a method defined earlier. Both `self.method()` and `Self.method(...)` dispatch work. Only the canonical `name : (fn(...) -> R)(body)` method shape participates; bare lambdas do not get forward-ref shells.
134
152
  - **Module-level `::` function definitions are processed in order.** A function body that calls another function declared later in the same file will fail with "Variable not found". Always define leaf helpers first (bottom-up order): `eval_identifier` → `eval_atom` → `evaluate`.
@@ -164,7 +182,7 @@ safe_divide :: (fn(x : i32, y : i32, using(raise : Raise)) -> i32)(
164
182
 
165
183
  caller :: (fn() -> i32)({
166
184
  (given(raise) : Raise) = (fn(msg : String) -> i32)({
167
- return i32(0);
185
+ return(i32(0));
168
186
  });
169
187
 
170
188
  safe_divide(i32(10), i32(0))
@@ -184,9 +202,9 @@ caller :: (fn() -> i32)({
184
202
  result := closure(i32(5));
185
203
 
186
204
  transform :: (fn(list : ArrayList(i32), f : Impl(Fn(x : i32) -> i32)) -> unit)({
187
- for list.iter(), (ptr) => {
205
+ for(list.iter(), (ptr) => {
188
206
  ptr.* = f(ptr.*);
189
- };
207
+ });
190
208
  });
191
209
  ```
192
210
 
@@ -198,15 +216,15 @@ transform :: (fn(list : ArrayList(i32), f : Impl(Fn(x : i32) -> i32)) -> unit)({
198
216
  ## Imports and modules
199
217
 
200
218
  ```rust
201
- { Parser } :: import "./parser.yo";
202
- parser_module :: import "./parser.yo";
219
+ { Parser } :: import("./parser.yo");
220
+ parser_module :: import("./parser.yo");
203
221
 
204
- open import "std/string";
205
- { ArrayList } :: import "std/collections/array_list";
222
+ open(import("std/string"));
223
+ { ArrayList } :: import("std/collections/array_list");
206
224
  ```
207
225
 
208
226
  - Use relative imports for nearby `.yo` files
209
- - 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
210
228
  - Do not write `import "./file.yo" as name`
211
229
  - Do not import `std/prelude`
212
230
 
@@ -268,17 +286,17 @@ show :: (fn(forall(T : Type), value : T, where(T <: ToString)) -> unit)(
268
286
 
269
287
  ```rust
270
288
  main :: (fn() -> unit)(());
271
- export main;
289
+ export(main);
272
290
 
273
- export
291
+ export(
274
292
  helper,
275
293
  Config
276
- ;
294
+ );
277
295
  ```
278
296
 
279
- - `export name;` exports a single binding
297
+ - `export(name);` exports a single binding
280
298
  - Block form exports multiple bindings separated by commas
281
- - Every executable needs `export main;`
299
+ - Every executable needs `export(main);`
282
300
 
283
301
  ## Static and dynamic dispatch types
284
302
 
@@ -316,15 +334,15 @@ factorial :: (fn(n : i32) -> i32)(
316
334
  )
317
335
  );
318
336
 
319
- // Runtime infinite loop — `while cond` is ALWAYS runtime
320
- while true, {
337
+ // Runtime infinite loop — `while(cond, body)` is ALWAYS runtime
338
+ while(true, {
321
339
  work();
322
- };
340
+ });
323
341
 
324
342
  // Compile-time loop unrolling — requires comptime() modifier
325
- while comptime(i < 10), {
343
+ while(comptime((i < 10)), {
326
344
  // body evaluated/unrolled at compile time
327
- };
345
+ });
328
346
 
329
347
  // for loop — 2-arg prelude macro; first arg MUST be an iterator (has .next()):
330
348
  for(list.iter(), x => { // ArrayList, array → call .iter() first
@@ -341,8 +359,8 @@ for(list.iter(), (ptr) => { // ptr is a mutable reference to each element
341
359
  ```
342
360
 
343
361
  - Use `recur(...)` for self-recursion
344
- - `while cond` is **always a runtime loop** — use this for open-ended loops (e.g., server accept loops, event loops)
345
- - `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
346
364
  - Using a comptime-only (`::`) variable in a bare `while` condition without `comptime()` is a **compile error** (would be an infinite loop at runtime)
347
365
  - **`for(arr, item => { body })`** — correct 2-arg prelude macro form. The `item => { body }` is an anonymous closure.
348
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`)
@@ -350,19 +368,19 @@ for(list.iter(), (ptr) => { // ptr is a mutable reference to each element
350
368
  ## Return and branch safety
351
369
 
352
370
  ```rust
353
- // WRONG — return consumes the comma, capturing the next match branch:
371
+ // WRONG — paren-less return is invalid:
354
372
  match(opt,
355
- .Some(v) => return v, // parsed as return(v, .None => ...)
373
+ .Some(v) => return v,
356
374
  .None => default_value()
357
375
  );
358
376
 
359
- // CORRECT — begin blocks isolate return from the comma:
377
+ // CORRECT — explicit return calls in begin blocks:
360
378
  match(opt,
361
379
  .Some(v) => {
362
- return v;
380
+ return(v);
363
381
  },
364
382
  .None => {
365
- return default_value();
383
+ return(default_value());
366
384
  }
367
385
  );
368
386
 
@@ -375,11 +393,11 @@ get_value :: (fn(opt : Option(i32)) -> i32)(
375
393
  );
376
394
  ```
377
395
 
378
- - `return expr1, expr2` parses as a single function call: `return(expr1, expr2)`
396
+ - `return expr` is invalid; write `return(expr)` or `return()` for unit
379
397
  - In `cond` or `match` branches, **always use begin blocks** when you need `return`
380
- - `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.
381
399
  - If the whole function is one expression, prefer expression-bodied style and skip `return` entirely
382
- - 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 `(...)`
383
401
 
384
402
  ## String concatenation pitfall
385
403
 
@@ -401,43 +419,43 @@ content := String.from("line1\nline2\n");
401
419
  ## Iterator and for loop
402
420
 
403
421
  ```rust
404
- { ArrayList } :: import "std/collections/array_list";
422
+ { ArrayList } :: import("std/collections/array_list");
405
423
 
406
424
  list := ArrayList(i32).new();
407
425
  list.push(i32(10));
408
426
  list.push(i32(20));
409
427
 
410
- for list.iter(), (ptr) => {
428
+ for(list.iter(), (ptr) => {
411
429
  println(ptr.*);
412
- };
430
+ });
413
431
 
414
- for list.into_iter(), (value) => {
432
+ for(list.into_iter(), (value) => {
415
433
  println(value);
416
- };
434
+ });
417
435
  ```
418
436
 
419
- - `for collection, (variable) => { body }` iterates via the `Iterator` trait
437
+ - `for(collection, (variable) => { body })` iterates via the `Iterator` trait
420
438
  - `.iter()` borrows the collection and yields pointers
421
439
  - `.into_iter()` takes ownership and yields values
422
440
 
423
441
  ## Testing
424
442
 
425
443
  ```rust
426
- test "Addition works", {
444
+ test("Addition works", {
427
445
  assert(((i32(1) + i32(1)) == i32(2)), "1+1 should be 2");
428
- };
446
+ });
429
447
 
430
- test "Compile-time check", {
448
+ test("Compile-time check", {
431
449
  comptime_assert((2 + 2) == 4);
432
450
  comptime_expect_error({ x :: (1 / 0); });
433
- };
451
+ });
434
452
 
435
- test "Async test", {
453
+ test("Async test", {
436
454
  io.await(yield());
437
- };
455
+ });
438
456
  ```
439
457
 
440
- - `test "description", { body }` defines a test — `io : IO` is automatically available
458
+ - `test("description", { body })` defines a test — `io : IO` is automatically available
441
459
  - All tests can use `io.async(...)`, `io.await(...)`, etc. without a `using` clause
442
460
  - `assert(condition, "message")` — runtime assertion (always include a message)
443
461
  - `comptime_assert(condition)` — compile-time assertion
@@ -666,7 +684,7 @@ if((!cond), { do_thing(); });
666
684
 
667
685
  ### `escape` requires a nested-function context
668
686
 
669
- `escape value` exits the **enclosing function** — the nearest `fn(...)` that
687
+ `escape(value)` exits the **enclosing function** — the nearest `fn(...)` that
670
688
  wraps the current code. It requires that the code is inside a nested function
671
689
  (e.g., a closure or `given` handler lambda), NOT at the top level of a
672
690
  standalone function definition.
@@ -674,20 +692,20 @@ standalone function definition.
674
692
  ```rust
675
693
  // CORRECT — escape inside a given handler lambda (lambda has enclosing fn):
676
694
  given(exn) := Exception(throw: ((err) -> {
677
- escape result // exits the outer function that contains this given()
695
+ escape(result); // exits the outer function that contains this given()
678
696
  }));
679
697
  do_something(using(exn));
680
698
 
681
699
  // CORRECT — escape inside a closure passed as argument:
682
700
  result := match(opt, .Some(x) => x, .None => {
683
701
  // This is NOT a nested function — use return:
684
- // WRONG: escape default_val // ERROR: no enclosing fn
685
- 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
686
704
  });
687
705
 
688
706
  // WRONG — escape inside a match arm (not a nested fn):
689
707
  match(opt,
690
- .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"
691
709
  );
692
710
  ```
693
711
 
@@ -918,16 +936,16 @@ if (((is_tuple_type(ty) || is_struct_type(ty)) || is_union_type(ty)), ...)
918
936
 
919
937
  ### Duplicate imports from the same path must be merged
920
938
 
921
- 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.
922
940
  Always merge them into a single destructuring import:
923
941
 
924
942
  ```rust
925
943
  // ❌ Two imports from the same path
926
- { Foo } :: import "../../mod.yo";
927
- { Bar } :: import "../../mod.yo";
944
+ { Foo } :: import("../../mod.yo");
945
+ { Bar } :: import("../../mod.yo");
928
946
 
929
947
  // ✅ Merged
930
- { Foo, Bar } :: import "../../mod.yo";
948
+ { Foo, Bar } :: import("../../mod.yo");
931
949
  ```
932
950
 
933
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