feat(udp): Udp.* - polled IPv4 datagrams on macOS and Windows

Udp.open/port/send/recv/from_ip/from_port/close/resolve/local_ip/ip/ip_text, native
BSD sockets (udp.ll) and Winsock (udp_win.ll, -lws2_32), linked only when a program
uses Udp.*; example, docs and tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-17 11:16:14 +03:00
parent 6a7f1dd393
commit ebb1a00352
24 changed files with 68630 additions and 66360 deletions

View file

@ -731,6 +731,20 @@ function cmd_dev_test() -> int {
else { bad2("http.ludic via ludic build", `got [{got2}]`) }
} else { bad2("ludic build of an Http.* program", capture_line(`tail -1 {tmp_dir()}/http_lb.out`)) }
}
# Udp.*: two sockets on the loopback, a datagram each way, through ludicc and ludic build
if is_darwin() {
let udp_want = "2 2 104 105 1 2 127.0.0.1 1 0 1"
if shq(`LUDIC_HOME=. bin/ludicc examples/library/udp.ludic -o {tmp_dir()}/udp_demo > {tmp_dir()}/udp.out 2>&1`) {
let got = capture_line(`{tmp_dir()}/udp_demo < /dev/null`)
if (got == udp_want) { ok("udp.ludic (Udp.open/send/recv/from/ip - datagrams over the loopback)") }
else { bad2("udp.ludic", `got [{got}]`) }
} else { bad2("udp.ludic build", capture_line(`tail -1 {tmp_dir()}/udp.out`)) }
if shq(`LUDIC_HOME=. bin/ludic build examples/library/udp.ludic --headless -o {tmp_dir()}/udp_lb > {tmp_dir()}/udp_lb.out 2>&1`) {
let got2 = capture_line(`{tmp_dir()}/udp_lb < /dev/null`)
if (got2 == udp_want) { ok("ludic build links udp.ll for a program that uses Udp.*") }
else { bad2("udp.ludic via ludic build", `got [{got2}]`) }
} else { bad2("ludic build of a Udp.* program", capture_line(`tail -1 {tmp_dir()}/udp_lb.out`)) }
}
feat_case("events/recurse", "", "16", "recurse.ludic (EV6: re-entrant emit is depth-bounded, no runaway cycle)")
net_case("events/scoped", "2")