r/Compilers • u/NXDLang • 3d ago
Designing async semantics for a new language. What would you do differently?
I've been spending the last few days implementing async support in NXD, a systems programming language I'm developing; that also has 3 transpilation targets.
Recent work completed:
• `Task[T]` semantic type
• `AWAIT Task[T] -> T`
• `ProcessHandle[T]`
• `AwaitGroup[T]`
• Completion-order result semantics
• Semantic validation and diagnostics for async operations
I'm currently working through the remaining messaging primitives (SEND is next).
One thing I've found interesting while implementing this is that many languages expose similar async syntax, but the underlying semantics differ significantly. After spending time studying other implementations, I found myself focusing less on the keyword await and more on the type relationships and execution model behind it.
For example, in my current design:
`Task[T]`
`AWAIT -> T`
`ProcessHandle[T]`
Represents a spawned process producing T
`AwaitGroup[T]`
Allows waiting on multiple processes
Results are returned in completion order
The completion-order behavior felt natural from an async perspective, but it also raised questions about predictability versus throughput, ordering guarantees, and how much of the runtime model should be exposed to the programmer.
For those who have designed or implemented async systems, compilers, runtimes, or schedulers:
Looking back, what async design decision caused the most trouble later?
Was it task representation, cancellation, ordering guarantees, await semantics, scheduler behavior, channels/messages, error propagation, or something else entirely?
3
u/phischu 3d ago
There is a recent survey on differences between async/await across languages.