feat(stdlib): namespaced standard library (issue #2)
Implement the bulk of the namespaced-stdlib proposal (workshopsoft/ludic#2): 156 namespace methods across Math, Text, List, Ease, Collide, World, Net, Sys, Save, Mem, extended Screen, Color functions, extended Random, and Time. All deterministic fixed-point; self-hosting (C-free bootstrap fixpoint holds). Compiler (selfhost/): - Math.*: sqrt/sin/cos/tan/atan2/asin/acos (fixed-point runtime prelude — bit-by-bit isqrt, 256-entry interpolated sine table, Ross atan2), plus hypot/dist/dist2/deg_to_rad/rad_to_deg/posmod/wrap/ping_pong/snapped/ move_toward/smoothstep/lerp/remap/sign/floor/ceil/round. - Text.* (complete): upper/lower/trim/repeat/pad, split/join/replace, and the libc-backed queries. - List.* (complete): insert/remove_at/remove/sort plus the earlier ops. - Ease.* (in/out/in_out/back/bounce) and Collide.* (rects/point_rect/ circles/rect_circle). - Phase 3: World/Net/Sys/Save namespaced over the bare builtins (byte- identical IR) and Mem.* (bytes/words/copy/fill/peek/poke). - Screen.* extended (line/circle/fill_circle/triangle/fill_triangle via new runtime primitives; sprite/sprite_scaled aliases), Color.* functions, Random.* (value/int/sign), Time.* (frame/delta/elapsed/now — new game-loop frame counter). - Fix a lexer bug: fixed-point literals with >4 fractional digits overflowed. Docs & tooling: - 129 new per-symbol doc pages; gen.py made data-driven (namespaces discovered from the docs, no hardcoded list); new check-impl.py enforces that every implemented namespace method / keyword / type / phase has a doc page, wired into `x test-tools`. Document the previously-undocumented keywords (break/continue/where/entry/new/public + and/or/not tokens). - LSP: namespaced signature help (ns_method_sig) covering every namespace. Tests: 12 new self-host/regression tests + a golden render for the drawing primitives. All suites green (selfhost 21, regression 45, tools 29). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ff15c4e01d
commit
a38195128f
235 changed files with 24676 additions and 7762 deletions
27
docs/language/control/kw-break.md
Normal file
27
docs/language/control/kw-break.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
id: kw-break
|
||||
name: break
|
||||
category: control
|
||||
kind: keyword
|
||||
tokens: break
|
||||
sig: break
|
||||
tip: Leave the enclosing loop immediately.
|
||||
order: 9
|
||||
---
|
||||
|
||||
<code>break</code> exits the innermost <code>while</code> or <code>for</code> loop at once, skipping the rest of the body and any remaining iterations, and continues with the code after the loop. Use it to stop early the moment you have what you need — the first match in a scan, a collision that ends the sweep, or a guard inside <code>while true</code> that decides when to leave. It affects only the loop that contains it; an outer loop keeps running.
|
||||
|
||||
```ludic
|
||||
program FindFirst {
|
||||
var found: int = 0 - 1
|
||||
|
||||
handler Scan phase Update {
|
||||
for i in 0 .. 10 {
|
||||
if i * i > 20 {
|
||||
found = i
|
||||
break # stop at the first i whose square exceeds 20
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
25
docs/language/control/kw-continue.md
Normal file
25
docs/language/control/kw-continue.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
id: kw-continue
|
||||
name: continue
|
||||
category: control
|
||||
kind: keyword
|
||||
tokens: continue
|
||||
sig: continue
|
||||
tip: Skip to the next iteration of the loop.
|
||||
order: 10
|
||||
---
|
||||
|
||||
<code>continue</code> abandons the rest of the current loop pass and jumps straight to the next one — the next condition check in a <code>while</code>, or the next index in a <code>for</code>. Use it to skip elements that do not apply without nesting the rest of the body inside an <code>if</code>: filter out empty slots, ignore inactive entities, or step over even numbers. Like <code>break</code>, it acts on the innermost loop only.
|
||||
|
||||
```ludic
|
||||
program SumOdds {
|
||||
var total: int = 0
|
||||
|
||||
handler Add phase Update {
|
||||
for i in 0 .. 10 {
|
||||
if i % 2 == 0 { continue } # skip even numbers
|
||||
total = total + i
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
25
docs/language/control/kw-where.md
Normal file
25
docs/language/control/kw-where.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
id: kw-where
|
||||
name: where
|
||||
category: control
|
||||
kind: keyword
|
||||
tokens: where
|
||||
sig: for (Binds) in query [Comps] where cond { … }
|
||||
tip: Filter a query loop to entities that satisfy a condition.
|
||||
order: 11
|
||||
---
|
||||
|
||||
<code>where</code> attaches a boolean condition to a <code>query</code> loop, so the body runs only for entities whose components satisfy it — the rows that fail the test are skipped entirely. The condition is an ordinary expression over the bound components, such as <code>where Battle.hp <= 0 and Battle.side == 1</code>. It is the imperative twin of a component filter written inside a <code>@Queries</code> annotation, and keeps the guard next to the loop instead of repeating an <code>if</code> at the top of the body.
|
||||
|
||||
```ludic
|
||||
program Cleanup {
|
||||
property Health { hp: int = 0 }
|
||||
model Foe { Health }
|
||||
|
||||
handler ReapDead phase LateUpdate {
|
||||
for (Health) in query [Health, {Foe}] where Health.hp <= 0 {
|
||||
# only dead foes reach here
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue