Toolchain composition

A toolchain is a particularly demanding consumer of its own infrastructure. It has to read source, find dependencies, select implementations and produce something another system can use. If each of those steps depends on private classes from the others, replacing one tool quickly becomes a project-wide change.

Godot already chooses a provider and invokes the image operations it negotiates. For the toolchain to do the same, an execution model has to remain usable even when its objects came from an unfamiliar dialect. Otherwise loading another language would still require teaching every terminal about that language's parser classes.

What belongs to a dialect?

Library provides one way to author Type and Execution objects. Its parser can attach source locations and documentation without making those facts mandatory for every instance of the model. A loaded package or another language should be able to supply the same execution contracts with different provenance, or with no authored source at all.

Shader and App benefit from this distinction too. They may share parser fragments where the syntax actually matches, but using a CPU execution fact shouldn't mean importing Library as a language. App can find an entry, validate its callable agreement and let a terminal generate from those facts.

This is a substantial part of the current migration. The older toolchain could perform useful work, but too much of its composition relied on native C++ type relationships. Moving the boundaries makes those assumptions visible and gives foreign providers a place to participate.

Bootstrapping the next capability

Something still has to make the first call. A module entry has a prearranged ABI and supplies an owned Abstract acquisition, with host services already available through their agreed surface. Once that initial relationship exists, the caller can negotiate the capabilities needed for the next part of the work.

A Build dialect can use that arrangement to describe how a project acquires and connects its tools. It needn't make the source parser responsible for loading binaries, interpreting execution models and managing every emitted product. Those participants can expose their own contracts and lifetimes.

The project-source CUDA example is a useful step in this direction. The project knows what a kernel means for an image operation, while the CUDA service knows how to compile and execute it. A more general build system would have more work to do, but it should preserve that division rather than absorb both sides.

Giving the host a smaller job

Puffer is the command-line and language-server host for Tetrodotoxin. The goal is for it to arrange a request and retain the relevant session state while selected dialects and terminals perform their own work.

An editor makes the ownership questions difficult in productive ways. A source file may be incomplete, an older generation may still be borrowed, and a query may become obsolete while another edit is being processed. Putting those rules into the source and session owners lets the lower transport layer remain useful without teaching it how an editor works.

The portable Build and Package/Workspace interfaces are still being developed. The next convincing example is a complete, bounded source-to-product path: load a provider, interpret through its dialect, expose the resulting model to a terminal, and use the emitted result after discovery has ended. The Source examples already test parts of that lifetime. Carrying it through the rest of the toolchain will tell us which agreements are still missing.

The Puffer overview describes the host, and the Source chapter follows the invocation boundary it will use.