@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.
- package/.github/skills/yo-async-effects/SKILL.md +4 -4
- package/.github/skills/yo-async-effects/async-effects-recipes.md +34 -34
- package/.github/skills/yo-core-patterns/SKILL.md +1 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +26 -26
- package/.github/skills/yo-project-workflow/SKILL.md +6 -3
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
- package/.github/skills/yo-syntax/SKILL.md +7 -6
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +73 -60
- package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
- package/README.md +10 -8
- package/out/cjs/index.cjs +456 -438
- package/out/cjs/yo-cli.cjs +576 -543
- package/out/cjs/yo-lsp.cjs +559 -532
- package/out/esm/index.mjs +281 -263
- package/out/types/src/formatter.d.ts +11 -0
- package/out/types/src/lsp/formatting.d.ts +2 -0
- package/out/types/src/tests/formatter.test.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/alg/hash.yo +13 -21
- package/std/allocator.yo +25 -40
- package/std/async.yo +3 -7
- package/std/build.yo +105 -151
- package/std/cli/arg_parser.yo +184 -169
- package/std/collections/array_list.yo +350 -314
- package/std/collections/btree_map.yo +142 -131
- package/std/collections/deque.yo +132 -128
- package/std/collections/hash_map.yo +542 -566
- package/std/collections/hash_set.yo +623 -687
- package/std/collections/linked_list.yo +275 -293
- package/std/collections/ordered_map.yo +113 -85
- package/std/collections/priority_queue.yo +73 -73
- package/std/crypto/md5.yo +191 -95
- package/std/crypto/random.yo +56 -64
- package/std/crypto/sha256.yo +151 -107
- package/std/encoding/base64.yo +87 -81
- package/std/encoding/hex.yo +43 -50
- package/std/encoding/html.yo +56 -81
- package/std/encoding/html_char_utils.yo +7 -13
- package/std/encoding/html_entities.yo +2248 -2253
- package/std/encoding/json.yo +316 -224
- package/std/encoding/punycode.yo +86 -116
- package/std/encoding/toml.yo +67 -66
- package/std/encoding/utf16.yo +37 -44
- package/std/env.yo +62 -91
- package/std/error.yo +7 -15
- package/std/fmt/display.yo +5 -9
- package/std/fmt/index.yo +8 -14
- package/std/fmt/to_string.yo +330 -315
- package/std/fmt/writer.yo +58 -87
- package/std/fs/dir.yo +83 -102
- package/std/fs/file.yo +147 -180
- package/std/fs/metadata.yo +45 -78
- package/std/fs/temp.yo +55 -65
- package/std/fs/types.yo +27 -40
- package/std/fs/walker.yo +53 -68
- package/std/gc.yo +5 -8
- package/std/glob.yo +30 -43
- package/std/http/client.yo +107 -120
- package/std/http/http.yo +106 -96
- package/std/http/index.yo +4 -6
- package/std/imm/list.yo +88 -93
- package/std/imm/map.yo +528 -464
- package/std/imm/set.yo +52 -57
- package/std/imm/sorted_map.yo +340 -286
- package/std/imm/sorted_set.yo +57 -63
- package/std/imm/string.yo +404 -345
- package/std/imm/vec.yo +173 -181
- package/std/io/reader.yo +3 -6
- package/std/io/writer.yo +4 -8
- package/std/libc/assert.yo +5 -9
- package/std/libc/ctype.yo +32 -22
- package/std/libc/dirent.yo +26 -25
- package/std/libc/errno.yo +164 -90
- package/std/libc/fcntl.yo +52 -45
- package/std/libc/float.yo +66 -44
- package/std/libc/limits.yo +42 -33
- package/std/libc/math.yo +53 -82
- package/std/libc/signal.yo +72 -47
- package/std/libc/stdatomic.yo +217 -188
- package/std/libc/stdint.yo +5 -29
- package/std/libc/stdio.yo +5 -29
- package/std/libc/stdlib.yo +32 -39
- package/std/libc/string.yo +5 -23
- package/std/libc/sys/stat.yo +58 -56
- package/std/libc/time.yo +5 -19
- package/std/libc/unistd.yo +5 -20
- package/std/libc/wctype.yo +6 -9
- package/std/libc/windows.yo +26 -30
- package/std/log.yo +41 -55
- package/std/net/addr.yo +102 -97
- package/std/net/dns.yo +27 -28
- package/std/net/errors.yo +50 -49
- package/std/net/tcp.yo +113 -124
- package/std/net/udp.yo +55 -66
- package/std/os/env.yo +35 -33
- package/std/os/signal.yo +15 -25
- package/std/path.yo +276 -311
- package/std/prelude.yo +6304 -4315
- package/std/process/command.yo +87 -103
- package/std/process/index.yo +12 -31
- package/std/regex/compiler.yo +196 -95
- package/std/regex/flags.yo +58 -39
- package/std/regex/index.yo +157 -173
- package/std/regex/match.yo +20 -31
- package/std/regex/node.yo +134 -152
- package/std/regex/parser.yo +283 -259
- package/std/regex/unicode.yo +172 -202
- package/std/regex/vm.yo +155 -171
- package/std/string/index.yo +5 -7
- package/std/string/rune.yo +45 -55
- package/std/string/string.yo +937 -964
- package/std/string/string_builder.yo +94 -104
- package/std/string/unicode.yo +46 -64
- package/std/sync/channel.yo +72 -73
- package/std/sync/cond.yo +31 -36
- package/std/sync/mutex.yo +30 -32
- package/std/sync/once.yo +13 -16
- package/std/sync/rwlock.yo +26 -31
- package/std/sync/waitgroup.yo +20 -25
- package/std/sys/advise.yo +16 -24
- package/std/sys/bufio/buf_reader.yo +77 -93
- package/std/sys/bufio/buf_writer.yo +52 -65
- package/std/sys/clock.yo +4 -9
- package/std/sys/constants.yo +77 -61
- package/std/sys/copy.yo +4 -10
- package/std/sys/dir.yo +26 -43
- package/std/sys/dns.yo +41 -61
- package/std/sys/errors.yo +95 -103
- package/std/sys/events.yo +45 -57
- package/std/sys/externs.yo +319 -267
- package/std/sys/fallocate.yo +7 -11
- package/std/sys/fcntl.yo +14 -22
- package/std/sys/file.yo +26 -40
- package/std/sys/future.yo +5 -8
- package/std/sys/iov.yo +12 -25
- package/std/sys/lock.yo +12 -13
- package/std/sys/mmap.yo +38 -43
- package/std/sys/path.yo +3 -8
- package/std/sys/perm.yo +7 -21
- package/std/sys/pipe.yo +5 -12
- package/std/sys/process.yo +23 -29
- package/std/sys/seek.yo +10 -12
- package/std/sys/signal.yo +7 -13
- package/std/sys/signals.yo +52 -35
- package/std/sys/socket.yo +63 -58
- package/std/sys/socketpair.yo +3 -6
- package/std/sys/sockinfo.yo +11 -20
- package/std/sys/statfs.yo +11 -34
- package/std/sys/statx.yo +25 -52
- package/std/sys/sysinfo.yo +15 -20
- package/std/sys/tcp.yo +62 -92
- package/std/sys/temp.yo +5 -9
- package/std/sys/time.yo +5 -15
- package/std/sys/timer.yo +6 -11
- package/std/sys/tty.yo +10 -18
- package/std/sys/udp.yo +22 -39
- package/std/sys/umask.yo +3 -6
- package/std/sys/unix.yo +33 -52
- package/std/testing/bench.yo +49 -52
- package/std/thread.yo +10 -15
- package/std/time/datetime.yo +105 -89
- package/std/time/duration.yo +43 -56
- package/std/time/instant.yo +13 -18
- package/std/time/sleep.yo +5 -9
- package/std/url/index.yo +184 -209
- package/std/worker.yo +6 -10
|
@@ -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
|
|
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
|
|
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
|
|
37
|
-
| ----------------- |
|
|
38
|
-
| Single expression | `cond(...)`
|
|
39
|
-
| Begin block | `{ 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
|
-
-
|
|
105
|
-
- `func
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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
|
|
207
|
-
parser_module :: import
|
|
219
|
+
{ Parser } :: import("./parser.yo");
|
|
220
|
+
parser_module :: import("./parser.yo");
|
|
208
221
|
|
|
209
|
-
open
|
|
210
|
-
{ ArrayList } :: import
|
|
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
|
|
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
|
|
289
|
+
export(main);
|
|
277
290
|
|
|
278
|
-
export
|
|
291
|
+
export(
|
|
279
292
|
helper,
|
|
280
293
|
Config
|
|
281
|
-
;
|
|
294
|
+
);
|
|
282
295
|
```
|
|
283
296
|
|
|
284
|
-
- `export
|
|
297
|
+
- `export(name);` exports a single binding
|
|
285
298
|
- Block form exports multiple bindings separated by commas
|
|
286
|
-
- Every executable needs `export
|
|
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
|
|
325
|
-
while
|
|
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
|
|
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
|
|
350
|
-
- `while
|
|
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
|
|
371
|
+
// WRONG — paren-less return is invalid:
|
|
359
372
|
match(opt,
|
|
360
|
-
.Some(v) => return v,
|
|
373
|
+
.Some(v) => return v,
|
|
361
374
|
.None => default_value()
|
|
362
375
|
);
|
|
363
376
|
|
|
364
|
-
// CORRECT —
|
|
377
|
+
// CORRECT — explicit return calls in begin blocks:
|
|
365
378
|
match(opt,
|
|
366
379
|
.Some(v) => {
|
|
367
|
-
return
|
|
380
|
+
return(v);
|
|
368
381
|
},
|
|
369
382
|
.None => {
|
|
370
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
428
|
+
for(list.iter(), (ptr) => {
|
|
416
429
|
println(ptr.*);
|
|
417
|
-
};
|
|
430
|
+
});
|
|
418
431
|
|
|
419
|
-
for
|
|
432
|
+
for(list.into_iter(), (value) => {
|
|
420
433
|
println(value);
|
|
421
|
-
};
|
|
434
|
+
});
|
|
422
435
|
```
|
|
423
436
|
|
|
424
|
-
- `for
|
|
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
|
|
444
|
+
test("Addition works", {
|
|
432
445
|
assert(((i32(1) + i32(1)) == i32(2)), "1+1 should be 2");
|
|
433
|
-
};
|
|
446
|
+
});
|
|
434
447
|
|
|
435
|
-
test
|
|
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
|
|
453
|
+
test("Async test", {
|
|
441
454
|
io.await(yield());
|
|
442
|
-
};
|
|
455
|
+
});
|
|
443
456
|
```
|
|
444
457
|
|
|
445
|
-
- `test
|
|
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
|
|
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
|
|
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
|
|
690
|
-
return
|
|
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
|
|
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
|
|
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
|
|
932
|
-
{ Bar } :: import
|
|
944
|
+
{ Foo } :: import("../../mod.yo");
|
|
945
|
+
{ Bar } :: import("../../mod.yo");
|
|
933
946
|
|
|
934
947
|
// ✅ Merged
|
|
935
|
-
{ Foo, Bar } :: import
|
|
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
|
|
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
|
|
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
|
|
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
|
-
```
|
|
206
|
-
{ println } :: import
|
|
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
|
|
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
|
-
```
|
|
259
|
+
```rust
|
|
258
260
|
// main.yo
|
|
259
|
-
{ println } :: import
|
|
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
|
|
267
|
+
export(main);
|
|
266
268
|
|
|
267
269
|
// $ yo compile main.yo --release -o main
|
|
268
270
|
// $ ./main
|