The Toolkit API is not a single library or module, but the core design philosophy that underpins the entire Ribbon ecosystem. The philosophy here may be summed up as “take what you need, and I’ll get out of your way when you know what you’re doing.” This philosophy manifests in two distinct but related ways: in the language’s design, which offers a full spectrum of control to the end-user, and in the toolchain’s architecture, which is fully modular and customizable for the platform developer.
A Spectrum of Control
Ribbon is designed to meet you where you are. It provides a layered, “pay-as-you-go” approach to complexity, allowing you to seamlessly move from high-level scripting to low-level systems programming within a single, unified language.
-
The Scripting Layer: At its most approachable, Ribbon can be used like a modern, dynamically-typed scripting language. You can write simple scripts without ever needing to write an explicit type annotation, making it ideal for rapid prototyping and simple tasks.
-
Gradual Static Typing: As a project’s complexity grows, you can introduce static types to functions and data structures. This brings the benefits of compile-time safety, robust refactoring, and better performance, allowing you to add rigor exactly where it’s needed.
-
Explicit Memory Management: For performance-critical code, you can move beyond the default memory management and take full control using Composable Allocation Strategies. You can choose to allocate memory from specific arenas, manage lifetimes explicitly, and reason about the memory usage of your application, all guided and verified by the type system.
-
Total Layout Control: For the deepest level of systems programming, such as C interoperability or hardware-level data manipulation, Ribbon provides total control over memory layout. Using Structural Data and layout polymorphism, you can specify the precise bit offset and memory region of your values, guaranteeing ABI compatibility and maximum data density.
This layered design means you are never forced to pay the cognitive overhead for a level of control you don’t need, but the power is always there when you do.
A Modular and Composable Platform
This “toolkit” philosophy extends to the very construction of the Ribbon compiler and runtime. Ribbon is not delivered as a monolithic, black-box executable. Instead, it is a collection of modular libraries that can be composed, customized, and extended by a platform developer.
-
Modular Compiler Phases: The parser, type checker, and code generator are all distinct, swappable components. A platform developer could, for example, add a custom analysis pass after the type checker, or target a completely new architecture by plugging in a different code generation backend.
-
Customizable Runtime Environments: The true power for an embedded language comes from the host’s ability to define the guest’s world. By providing handlers for Algebraic Effects, the host application has complete authority over what guest code can do. For example, a host can:
- Provide a
FileSystem
effect handler that redirects all file access to a virtual, sandboxed filesystem. - Intercept memory
alloc
effects to enforce strict memory quotas on guest code. - Expose host functionality as custom effects, creating a secure, high-performance bridge between the host and guest without complex FFI.
- Provide a
-
Full Control Over the Build Process: The build orchestrator is itself a part of the toolkit, enabling advanced features like Hot Module Reloading by giving the developer programmatic control over the incremental compilation and state migration process.
The Toolkit API is Ribbon’s answer to the challenge of being both a powerful systems language for hosts and a safe, easy-to-use extension language for guests. It provides a rich set of tools, from high-level abstractions down to low-level primitives, and empowers developers to choose the right tool for the job, creating applications that are as safe, performant, and flexible as their domain requires.