Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/releases/v0.53.0.md

Nocter v0.53.0 Release Notes

Nocter v0.53.0 adds the standard-library foundations for structured network services. Programs can own a runtime-sized set of concurrent computations, accept bounded HTTP/1.1 requests, and transfer unique response authority without a framework or hidden task registry.

This release also separates incremental codec transformation from destination I/O. In-memory JSON generation therefore no longer acquires a blocking effect from the writer adapter that reuses the same spelling and traversal rules.

Effect-Neutral JSON Generation

Compact JSON generation now has one nonrecursive pull encoder. The encoder owns semantic traversal and exact JSON spelling, then yields borrowed byte chunks to destination-specific drivers. json.stringify collects those chunks into an owned String without becoming blocking; json.write drives the same encoder through a BlockingWriter and retains its destination effect.

The encoder keeps traversal frames instead of constructing a second semantic tree. Deep values, escaping, number spelling, object member order, allocation failure, and writer failure therefore cross one transformation authority.

Dynamic Structured Task Groups

TaskGroup<T> owns a runtime-sized Vec<future T>:

var tasks: TaskGroup<bool> = TaskGroup.empty()
tasks.add(check_first())
tasks.add(check_second())

while !tasks.is_empty() {
    let completed = await tasks.next() otherwise { return false }
    if !completed { return false }
}

Adding transfers ownership of a lazy computation. Awaiting next drives retained children fairly and removes one completion-order result. Cancelling a pending next ends only its borrow; destroying the group cancels every child still retained by the group. Fixed-arity task.join and task.race remain convenient structured operations over the same lifecycle model.

Asynchronous HTTP Server

std/http now provides Server, ServerConnection, IncomingRequest, Responder, and OutgoingResponse. Their ownership states permit one request and one response per accepted connection:

let connection = await server.accept_with_timeout(timeout)?
let exchange = await connection.read_request_with_timeout(timeout)?
let request = move exchange.0
let responder = move exchange.1

var response = OutgoingResponse.ok()
response.set_text_body(request.target())
await responder.respond_with_timeout(move response, timeout)?

The request decoder accepts strict HTTP/1.1 origin-form requests, requires one non-empty Host, and supports bounded fixed, chunked, and bodyless framing. It rejects conflicting framing and buffered pipelining. Response encoding owns protocol fields, final-status rules, HEAD suppression, and connection closure. Public Limits bound retained start lines, heads, fields, framing lines, and bodies.

Each timeout-bearing server operation applies one fixed deadline to the complete operation. An expired accept preserves its borrowed listener; an expired request read or response write destroys the consuming connection state. Applications own concurrent admission by retaining handler futures in a TaskGroup, so capacity cannot disagree with hidden server state.

Complete Service and Tooling

The new http-service example runs three concurrent loopback clients through a two-slot handler group. It checks two successful responses and one explicit no-response cleanup path, with finite deadlines on every network operation.

Hover, completion, declaration navigation, and implementation navigation expose the new public server typestate from the checked std/http contract. Native and installed-image tests exercise task-group completion, deadline cancellation, listener reuse, request decoding, response transfer, and complete service execution.

Compatibility and Non-goals

Existing JSON generation and HTTP client source remains valid. The new server deliberately does not add keep-alive, pipelining, protocol upgrade, CONNECT tunnels, streaming bodies, HTTP/2, HTTP/3, or an application framework. Those features require future public typestates rather than hidden state inside the bounded one-request API.

Release Qualification

Release-content commit fb75c5144b90e5ef845401394f21252e296aecdc passed the complete disposable compiler gate. Two independent optimized builds produced byte-identical archives and recursively identical installed homes. The retained archive is 9,201,893 bytes with SHA-256 3592964368201cabc821a72a96b76fcd374caeb009a49a11db28f4bb7c910424 and contains exactly 314 standard-library files. A fresh extraction passed version and installation diagnosis, locked/offline package workflows, native build and execution, every public example, the bounded HTTP service success and explicit no-response paths, framed LSP analysis, immutability checks, and compiler and standard-library tamper rejection. The published release reused this exact retained archive without rebuilding it.