feat(http): Http.* poll-based HTTP/HTTPS client over a native NSURLConnection backend (#6)
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 19s
ci / build-and-test (push) Successful in 1m26s
commit-lint / conventional-commits (push) Successful in 5s
docs / build-and-deploy (push) Successful in 21s

Adds the Http.* namespace and its transport, the HTTP client from #6. The JSON
companion the proposal called for already shipped as Json.* (#44).

- runtime/native/http.ll: the macOS transport — NSURLConnection driven through
  the objc runtime C ABI (no ObjC/C source), run on a detached pthread so the
  frame never blocks; TLS is the system's, on by default. A fixed slot pool holds
  each in-flight request; the worker publishes status/body/response behind an
  atomic done flag (release/acquire). Spliced + Foundation linked only when a
  program uses Http.*.
- runtime/native/http.ludic: the Http.* runtime — get/post/request, the
  open/set/body/send builder, poll/status/ok/text/body_len/header/free, plus a
  pure-Ludic response parser (Http.parse + case-insensitive header lookup) that
  is transport-independent and portable.
- compiler: Http.* dispatch, g_uses_http splice, hs_* transport intrinsics +
  declarations, the conditional Foundation link, and a new \r string/char escape
  the protocol needs.
- docs: a full docs/language/http section (16 pages); check-impl/check-docs green.
- test: examples/library/http.ludic self-asserts the parser offline (Darwin-gated
  build via the canonical path, since it links Foundation).

Verified end to end against real endpoints: HTTPS GET (200 + headers + body) and
POST (body + custom header). HTTP is out-of-band and never feeds the
deterministic sim. Reseeded; suites green (81 + 29).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-08-31 18:10:53 +03:00
parent 4eef5ebbce
commit 3df6640fa5
29 changed files with 24936 additions and 22396 deletions

View file

@ -231,6 +231,27 @@ function emit_ns_call(ns: pointer, meth: pointer, e: Node) -> Val {
if (meth == "pitch") { bare = "audio_pitch"; push(labels, "v") }
if (meth == "is_playing") { bare = "audio_is_playing"; push(labels, "id") }
}
# Http.* (#6) — a poll-based HTTP/HTTPS client (runtime/native/http.ludic +
# http.ll). Out-of-band, never part of the deterministic sim. Pairs with Json.*
# (#44) for (de)serialization: Json.parse(Http.text(h)).
if (ns == "Http") {
if (meth == "get") { bare = "http_get"; push(labels, "url") }
if (meth == "post") { bare = "http_post"; push(labels, "url"); push(labels, "body") }
if (meth == "request") { bare = "http_request"; push(labels, "method"); push(labels, "url"); push(labels, "body") }
if (meth == "open") { bare = "http_open"; push(labels, "method"); push(labels, "url") }
if (meth == "set") { bare = "http_set_header"; push(labels, "handle"); push(labels, "name"); push(labels, "value") }
if (meth == "body") { bare = "http_body"; push(labels, "handle"); push(labels, "body") }
if (meth == "body_bytes"){ bare = "http_body_n"; push(labels, "handle"); push(labels, "bytes"); push(labels, "len") }
if (meth == "send") { bare = "http_send_req"; push(labels, "handle") }
if (meth == "poll") { bare = "http_poll"; push(labels, "handle") }
if (meth == "status") { bare = "http_status_of"; push(labels, "handle") }
if (meth == "ok") { bare = "http_ok"; push(labels, "handle") }
if (meth == "text") { bare = "http_text"; push(labels, "handle") }
if (meth == "body_len") { bare = "http_body_len"; push(labels, "handle") }
if (meth == "header") { bare = "http_header_of"; push(labels, "handle"); push(labels, "name") }
if (meth == "free") { bare = "http_close"; push(labels, "handle") }
if (meth == "parse") { bare = "http_parse"; push(labels, "bytes"); push(labels, "len") }
}
# Phase 3: the bare reflection / networking / process builtins, namespaced.
# Each is a pure alias — the callee is rewritten to the bare name below.
if (ns == "World") {