@shd101wyy/yo 0.1.32 → 0.1.33

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.
@@ -160,13 +160,13 @@ process_dir :: (fn(root: Path, ctx : WalkCtx) -> Impl(Future(unit, WalkCtx)))(
160
160
  stack := ArrayList(Path).new();
161
161
  { stack.push(root); };
162
162
 
163
- while(runtime((stack.len() > usize(0))), {
163
+ while(stack.len() > usize(0), {
164
164
  cur := match(stack.pop(), .Some(p) => p, .None => return());
165
165
  entries := ctx.io.await(read_dir(cur, ctx.io), ctx.io);
166
166
  // process `entries`, push subdirectories to `stack`
167
167
  n := entries.len();
168
168
  i := usize(0);
169
- while(runtime((i < n)), {
169
+ while(i < n, {
170
170
  match(entries.get(i),
171
171
  .None => (),
172
172
  .Some(e) => {
@@ -78,6 +78,30 @@ text := match(parsed,
78
78
  - Prefer combinators for straight-line transforms: `map`, `and_then`, `map_err`, `or_else`
79
79
  - Switch to `match(...)` when branches need different logic or side effects
80
80
 
81
+ ### Match destructuring: prefer curly `{field}`, avoid positional `_` padding
82
+
83
+ For a variant with **2+ fields**, destructure by **name** with curly braces —
84
+ name only the fields the arm uses. Do NOT count positions and pad with `_`.
85
+
86
+ ```rust
87
+ // ✅ Curly — names only what you need; order-free; partial matches OK.
88
+ // Robust: adding a field to the variant later doesn't shift anything.
89
+ match(v,
90
+ .FuncVal({ func_id }) => use(func_id), // bind field `func_id`
91
+ .Struct({ id, name: n }) => use2(id, n), // rename via `field: alias`
92
+ .EnumT({ id }) => use3(id), // ignore the other 6 fields
93
+ _ => ()
94
+ )
95
+
96
+ // ❌ Avoid — positional with many `_`; brittle and unreadable:
97
+ // .FuncVal(_, _, _, _, _, _, _, _, func_id) => … // count the 8 _'s!
98
+ ```
99
+
100
+ `{a}` = bind field `a`; `{a: x}` = rename to `x`; `{a: _}` = assert-exists-ignore.
101
+ Empty `{}` and bare `{_}` are rejected. Spec: `tests/match_curly.test.yo`.
102
+ (Full rules: `.github/instructions/yo-syntax.instructions.md` § Match
103
+ destructuring forms.)
104
+
81
105
  ## Collections
82
106
 
83
107
  ```rust
@@ -303,7 +327,7 @@ node_eq :: (fn(a : Node, b : Node) -> bool)(
303
327
  true => {
304
328
  (i : usize) = usize(0);
305
329
  (ok : bool) = true;
306
- while(runtime(((i < acs.len()) && ok)), {
330
+ while(((i < acs.len()) && ok), {
307
331
  match(acs.get(i),
308
332
  .Some(ac) => match(bcs.get(i),
309
333
  .Some(bc) => { ok = recur(ac, bc); },
@@ -134,6 +134,7 @@ masked := ((A | B) | C);
134
134
  - **Audit public stdlib safety with `./yo-cli public-safe-report [path]`.** Flags every top-level public `fn(...)` whose params or return type expose `*(T)` outside an `extern(...)` block. Skips FFI-by-construction directories (`libc/`, `linux/`, `darwin/`, `cuda/`, `sys/`, `sync/`) and names that signal raw-pointer use by contract (`*_cstr`, `*_ptr`, `*_raw`, `raw_*`, `from_raw_parts`, `as_ptr`, `argv`, `argc`). Currently reports 0 findings on `./std` and `./yo-self`; keep it that way when adding new APIs.
135
135
  - **Extern "c" call sites require `unsafe(...)` even in pragma'd files.** `unsafe(memcpy(dst, src, n))`, `unsafe(strlen(s))`, etc. The pragma authorizes DECLARING the FFI symbol via `extern(...)` / `c_include(...)`; the wrap is the per-call audit marker so `yo unsafe-report` lines up with UB-capable lines. `asm(...)` and `extern(...)` / `c_include(...)` declarations themselves do NOT need a wrap (the keyword / declaration syntax is its own marker). See `plans/EXTERN_UNSAFE_WRAP.md`.
136
136
  - **Slice-flowability rule:** a function returning a slice-bearing type (`Slice(T)`, `str`, a struct wrapping a Slice, ...) must root the returned value in caller-owned storage (a `ref`-bound parameter, any non-`ref` parameter, a `comptime`/literal source, or a flowable projection chain). `(fn() -> Option(Slice(i32)))({ arr := ArrayList(i32).new(); arr.as_slice() })` is rejected; `(fn(ref(arr) : ArrayList(i32)) -> Option(Slice(i32)))(arr.as_slice())` is accepted. See `plans/SLICE_FLOWABILITY.md`.
137
+ - **Return-slot modifier placement: on the LABEL, not the type.** In a _labeled_ return slot, a `ref`/`comptime` modifier attaches to the label, mirroring the parameter convention (`ref(name) : T`). Valid: `-> ref(T)` and `-> comptime(T)` (unlabeled — modifier on the sole type), `-> (ref(name) : T)`, `-> (comptime(name) : T)`. **Rejected:** `-> (name : ref(T))`, `-> (name : comptime(T))` (modifier on the type when labeled), and `-> (ref(name) : ref(T))` (double-ref — "pick one"). Enforced at function-type eval in `src/evaluator/types/function.ts` (and the yo-self port).
137
138
  - **Signed-integer overflow is defined (wrap-around).** Yo passes `-fwrapv` to clang/gcc/zig by default so `x + i32(1)` on `i32(MAX)` wraps to `i32(MIN)` instead of UB. Opt-out: `--cflags='-fno-wrapv'`.
138
139
  - **`// SAFETY:` comment convention.** Every non-obvious `unsafe(...)` site in stdlib should have a `// SAFETY:` comment in the previous ~8 lines explaining the contract. `yo unsafe-report` picks them up and shows them inline under each finding.
139
140
  - **User-facing memory-safety guide:** `docs/en-US/MEMORY_SAFETY.md` (English) and `docs/zh-CN/MEMORY_SAFETY.md` (Chinese). Refer users there instead of `plans/MEMORY_SAFETY.md` (which is the design document — not shipped via npm).
@@ -524,7 +525,9 @@ divide :: (fn(x : i32, y : i32, requires(y != i32(0)), ensures(result == (x / y)
524
525
  increment :: (fn(ref(n) : i32, ensures(n == (old(n) + i32(1)))) -> unit)({ n = (n + i32(1)); });
525
526
 
526
527
  // invariant(...) must be the FIRST statement of a while body.
527
- while(runtime(i < n), {
528
+ // NOTE: do NOT wrap the condition in runtime(...) while conditions are
529
+ // runtime by default, so `while(runtime(i < n), …)` is redundant; use `while(i < n, …)`.
530
+ while(i < n, {
528
531
  invariant(i <= n, acc >= i32(0));
529
532
  i = (i + i32(1)); acc = (acc + i);
530
533
  });