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:
Orkun ÇAKILKAYA 2026-08-30 00:26:19 +03:00
parent ff15c4e01d
commit a38195128f
235 changed files with 24676 additions and 7762 deletions

View file

@ -0,0 +1,7 @@
---
id: net
title: Net
order: 6
---
The low-level networking seam — send and poll datagrams, serialize and apply entity state, and read ownership and role. Offline these collapse to single-player defaults.

View file

@ -0,0 +1,14 @@
---
id: net-apply
name: Net.apply
category: net
kind: namespace-method
tokens: Net.apply
sig: Net.apply(entity, buf) -> int
tip: Apply serialized state to an entity.
order: 3
ns: Net
member: apply
---
Reads synced fields from <code>buf</code> into <code>entity</code> — the inverse of <code>Net.serialize</code>.

View file

@ -0,0 +1,14 @@
---
id: net-is_owner
name: Net.is_owner
category: net
kind: namespace-method
tokens: Net.is_owner
sig: Net.is_owner(entity) -> bool
tip: Does this peer own the entity?
order: 7
ns: Net
member: is_owner
---
Returns true when this peer owns <code>entity</code> — <code>owner(entity) == local_id()</code>.

View file

@ -0,0 +1,14 @@
---
id: net-is_server
name: Net.is_server
category: net
kind: namespace-method
tokens: Net.is_server
sig: Net.is_server() -> bool
tip: Is this peer the server?
order: 6
ns: Net
member: is_server
---
Returns true on the authoritative peer. Offline it is true, so server-only guards run in single-player.

View file

@ -0,0 +1,14 @@
---
id: net-local_id
name: Net.local_id
category: net
kind: namespace-method
tokens: Net.local_id
sig: Net.local_id() -> int
tip: This peer's own id.
order: 8
ns: Net
member: local_id
---
Returns the network id of the local peer.

View file

@ -0,0 +1,14 @@
---
id: net-owner
name: Net.owner
category: net
kind: namespace-method
tokens: Net.owner
sig: Net.owner(entity) -> int
tip: The peer that owns an entity.
order: 4
ns: Net
member: owner
---
Returns the peer id that owns <code>entity</code>'s <code>@Owned</code> state.

View file

@ -0,0 +1,14 @@
---
id: net-poll
name: Net.poll
category: net
kind: namespace-method
tokens: Net.poll
sig: Net.poll(buf, cap) -> int
tip: Read an inbound datagram.
order: 1
ns: Net
member: poll
---
Reads up to <code>cap</code> bytes of the next inbound datagram into <code>buf</code> and returns the byte count, or zero when none is waiting.

View file

@ -0,0 +1,14 @@
---
id: net-send
name: Net.send
category: net
kind: namespace-method
tokens: Net.send
sig: Net.send(peer, buf, len) -> void
tip: Put a datagram on the wire.
order: 0
ns: Net
member: send
---
Sends the first <code>len</code> bytes of <code>buf</code> to <code>peer</code>. Absent a real socket it uses the built-in loopback, so offline code still runs.

View file

@ -0,0 +1,14 @@
---
id: net-serialize
name: Net.serialize
category: net
kind: namespace-method
tokens: Net.serialize
sig: Net.serialize(entity, buf) -> int
tip: Serialize an entity's synced state.
order: 2
ns: Net
member: serialize
---
Writes the <code>@Sync</code> fields of <code>entity</code> into <code>buf</code> and returns the byte count, for sending over the wire.

View file

@ -0,0 +1,14 @@
---
id: net-set_owner
name: Net.set_owner
category: net
kind: namespace-method
tokens: Net.set_owner
sig: Net.set_owner(entity, peer) -> void
tip: Assign ownership of an entity.
order: 5
ns: Net
member: set_owner
---
Sets the owning peer of <code>entity</code> to <code>peer</code>.