ADR-0002: C as the Core Implementation Language
Context
Ideal needs a primary language for its foundational components: the custom GUI toolkit, the desktop shell, the plugin runtime, and the core libraries that everything else builds upon. This choice affects developer productivity, long-term maintainability, contributor accessibility, and portability across target platforms.
The GUI toolkit will be built from scratch — existing toolkits cannot support the level of extensibility Ideal requires (plugin-extended widgets, cross-application features like universal autocomplete, deep keyboard-driven interaction). This means the core language must be well-suited for low-level graphics, input handling, text rendering, and system integration.
Most user-facing extensibility will happen through a tiered plugin system (scripting, WASM, and native), so the core language is primarily relevant to the small group of contributors working on foundational infrastructure, not to the broader plugin ecosystem.
Decision
We will use C (C23 standard) as the primary language for Ideal's core components: the toolkit, the desktop shell, the plugin runtime, and the core libraries. Individual modules or tools may use other languages when appropriate.
To address C's shortcomings in memory safety and standard library completeness, we commit to:
- C23 as the minimum standard, leveraging its improvements (nullptr, type-generic expressions, constexpr, typeof, improved enumerations, etc.).
- Strict compiler settings:
-Wall -Wextra -Werror -pedanticand additional targeted warnings. - Static analysis in CI: clang-tidy, clang static analyzer, or equivalent.
- Sanitizers in CI test runs: AddressSanitizer, UndefinedBehaviorSanitizer, and MemorySanitizer at minimum.
- Enforced code formatting via clang-format.
- A foundational library as one of the first deliverables, providing dynamic strings, dynamic arrays, hash maps, error handling conventions, and memory management primitives with clear ownership semantics.
Alternatives Considered
Rust. Offers memory safety without a garbage collector, a strong type system with pattern matching, and an excellent ecosystem for WASM runtimes and embedded scripting engines. However, the steep learning curve (the borrow checker in particular) significantly impacts developer productivity and raises the barrier for contributors. Rust's ecosystem for the target platforms is less mature than C's. The native plugin story is also more complex due to the lack of a stable ABI, requiring C FFI wrappers regardless.
C++. A superset of C with richer abstractions, used successfully for desktop toolkits (Qt, KDE). However, its complexity (multiple paradigms, ABI fragility, template metaprogramming) introduces more problems than it solves for this project. The additional features over C are not compelling enough given that the plugin system handles extensibility through other mechanisms.
Zig. An interesting systems language with excellent C interoperability and compile-time metaprogramming. Discarded because the language is pre-1.0, the ecosystem is immature, and betting core infrastructure on an unstable language specification is too risky for a long-lived project.
Consequences
- C is universally supported across target platforms with mature toolchains, and aligns with the systems ecosystem where Ideal operates (Wayland, D-Bus, ...) — contributors from these communities can participate without learning a new language.
- The foundational library is a significant upfront investment, but establishes consistent patterns and safety conventions for the entire codebase.
- Memory safety relies on discipline and tooling rather than language guarantees. If CI enforcement or code review rigor slips, so does safety.
- Plugin authors (the majority of contributors) are unaffected by this decision, as they will use the scripting layer, WASM, or the native C ABI.