Roadmap

Sun Language Roadmap

Features Sun still needs, ordered by priority — highest first. Completed features are removed from this list rather than ticked off.

The guiding principle: prioritise the work that turns "wait for the compiler team" into "a user can do it themselves". Table stakes before novelty.


Optionals — Remaining Work

Option<T> ships in the stdlib (stdlib/option.sun); _Result<T, E> is builtin and usable without the standard library. Both use generic payload enums with owning payloads and drop glue. The absence APIs (Map.find, String.find_char/rfind_char, Vec.first/last/pop, LinkedList.first/last) return Option<T>, and the iteration protocol (stdlib/iterator.sun) is next(ref Container) Option<T>. What remains:

  • Niche-optimised representation where possible (e.g. Option<raw_ptr<T>> as a nullable pointer)
  • Bare Some / None prelude names (today it is Option.Some(x) / Option.None)
  • Explicit Option<i32>.Some(...) in expression position
  • Nested-generic payload unification
  • Arrays and globals of payload enums
  • C-ABI classification of payload enums
  • Nested patterns in match
  • DW_TAG_variant_part debug info for payload enums

Constants and Compile-Time Evaluation

Routine requirements in embedded and safety-critical work, not niceties. Fixed-size array types (array<i32, 4>, array<f64, 2, 3>) exist, own their elements inline, and their dimensions are part of the type. Constant expressions, including calls to pure functions, are evaluated at compile time, and an array size can be the name of a constant: array<T, N>.

  • Generic value parameters: array<T, const N>
  • An array size computed by a function call, when the size is used by a class field or a function signature, or the function is declared below the use
  • Place compile-time const globals in read-only memory

Iteration Ergonomics

for (var x: Type in iterable) works but requires an explicit type annotation and there are no adapters. Verbose iteration is the first thing people mention when they bounce off a language.

  • Infer the element type in for ... in
  • Iterator adapters (map, filter, take, zip, enumerate)
  • Ranges as iterables
  • Iteration over a constant container: next(ref Container) takes a mutable borrow, so for … in needs a var iterable

Language Server Navigation

The LSP serves diagnostics, formatting, semantic tokens, hover type information, go-to-definition, find references and rename symbol today, plus a VS Code extension in extensions/vscode-sun. Autocomplete is the gap.

  • Autocomplete (must hide items that are not accessible from the cursor's module — use sun::access::isAccessible)

Testing

  • sun test runner (also emitted as a second <output>_test binary by -c; tests run in parallel by default, --test-sequential opts out)
  • Test declarations in .sun source (test_function, manifest test_files:)
  • Assertion builtins with useful failure output (std.test)
  • Test filtering (--test-filter geometry.*, repeatable, exact / module prefix / trailing-star patterns; a runtime argument like --test-sequential)
  • A thread pool for very large suites (today: one thread per test)

Error Handling Improvements

  • Stack traces on errors
  • panic / assert builtins
  • Error context and chaining

Library Expansion

Roughly 5,000 lines of stdlib today. Files and directories (std.io), environment (std.env), processes (std.process) and clocks (std.time) all exist. Every item below is something a first-day user hits. Most are community-supplyable now that FFI has landed.

  • Regex (expose the existing parser)
  • extern declarations for C globals and iterable std.env.Env
  • File metadata beyond exists/size, via statx (the one stat-family call whose struct has the same layout on every architecture)
  • Buffered stdin; std.io.read_line reads a byte at a time so it cannot swallow input a child process is about to read
  • String.c_str() as a const method: it writes the terminating NUL on demand, so every path-taking function (std.io, std.env, std.process) still takes ref String. Keeping the NUL as an invariant of the buffer would let them take const ref String. TLS is in the same position: TlsStream.connect and HttpsClient.get take the host as ref String for exactly this reason

Networking and TLS

TLS client and server transports, hostname resolution and an HTTPS client have landed: tls.moon wraps OpenSSL and carries a static copy of it, so TLS programs need no linker flags and no OpenSSL on the target. Remaining work:

  • Integrate TlsServerContext with HttpServer so it can serve HTTPS
  • IPv6, and connect/read timeouts on both TcpStream and TlsStream
  • Redirect following and connection reuse in HttpsClient
  • Fetch remote .moon bundles with the native client instead of shelling out to curl, dropping the package's curl dependency
  • Cross-target archives: tls.moon is built natively per platform — x86-64 musl archives on Linux (scripts/fetch-openssl.sh), arm64 Darwin archives on macOS (scripts/build-openssl-macos.sh), each selected by the manifest's target: block. What's missing is archives for cross builds (an aarch64 Linux target, or a Darwin tls.moon built from a Linux host) — the target: block also selects per OS only, not per architecture
  • Revisit the backend behind the same Sun API — a smaller vendored TLS library, or a pure-Sun implementation, without changing user code

Data Structures

Vec<T>, Map<K, V>, LinkedList<T>, Queue<T>, ContiguousBuffer<T>, String, Matrix<T>, BigUint, Unique<T> and Shared<T> exist today.

  • Set<T>
  • Stack<T>
  • OrderedMap<K, V>

Language Odds and Ends

  • Generic overloads that differ only in their constraint (one name, same parameter shape, <F: _Lambda> vs <F: _Function>) — duplicate generic declarations are rejected until overload resolution supports constraints (#194); spawn uses the union trait _Callable instead
  • Interface inheritance (src/semantic_analysis/scope_variables.cpp:876)
  • More sophisticated borrow tracking for ref params (src/borrow_checker/borrow_checker.cpp:385)
  • Proper float printing; print_f64 truncates to an integer (src/codegen/intrinsics/print.cpp:344)

Other Tooling

  • Linter (sunlint)
  • Source maps for error traces
  • Re-enable the DISABLED_ tests in tests/tooling/frontend/test_lexer.cpp

Native Protobuf Import — Deferred Items

protos: manifest imports synthesize Sun source per message (encode/decode, _delimited framing, Option<T> for proto3 optional, payload enums for oneof, unknown-field preservation, .moon export), byte-identical to libprotobuf. Docs: docs/pages/protobuf.mdx. Deferred:

  • proto2 syntax
  • group
  • Extensions
  • Recursive messages by value (need indirection)
  • --dump-proto-sun in the LSP

MacOS Target

Cross-compiling from Linux works and is covered by tests: --target arm64-apple-darwin produces Mach-O objects and a Darwin stdlib.moon (Apple AAPCS64 rules, per-OS stdlib sources via the manifest's target: block, __ulock in place of futex). The native-host support — Homebrew build, JITLink object layer, macOS search paths and a macos-latest CI job — is implemented but has not yet run on real hardware:

  • Validate on a Mac: the CI job green, JIT exceptions under JITLink (may need MachOPlatform/ORC runtime), Mutex under contention (__ulock), lldb stepping with -g, and Linux-cross-compiled objects linked and executed natively
  • A Homebrew formula (or tap) once native builds are validated

WebAssembly Target

  • WebAssembly — also the cheapest route to an online playground, which is the most effective adoption funnel a new language has

Robotics Middleware

Robotics systems are dozens to hundreds of processes communicating over a DDS through a pub-sub middleware. Sun ships the message layer (native protobuf import); the transport is the gap.

  • Custom DDS: discovery, topics, QoS, and a wire protocol
  • Pub-sub middleware on top of it, with protobuf messages as the payload
  • Interop with existing DDS implementations and ROS 2

Hardware Accelerators

Host Matrix<T> storage is complemented by optional NVIDIA-backed cuda.DeviceMatrix<T> operations. General Sun-written kernels and asynchronous device borrowing remain future work.

  • Offload kernels via LLVM Offload
  • Asynchronous device operations with lifetimes modelled by the borrow checker
  • Validate the NVIDIA backend on ARM64 SBSA and Jetson hardware

Tuples (maybe)

Under consideration, not committed to.

  • Tuple types: (i32, string)
  • Tuple construction: (1, "hello")
  • Destructuring: var (x, y) = pair;
  • Multiple return values without a named class

Open Design Decisions

  1. FFI lifetimes: extern calls require an unsafe block, and the convention is a safe Sun wrapper around it. What remains undecided is whether the borrow checker should model a pointer escaping into C at all — today ref T hands C an address with no lifetime tracking across the call.
  2. Generic instantiation: where do cross-module instantiations get emitted, and who owns deduplication — the compiler or the linker? (Today: use-site instantiation with link-time deduplication.)
  3. Memory model: should Vec<T> own its allocator or take a reference?
  4. Protobuf surface: import-only (.proto via manifest) shipped first. A native message declaration in Sun source with field: T = tag; syntax remains open — it would drive the same source generator (ProtoImporter) from a parser production instead of a FileDescriptor.

Last updated: August 2026