Flint logolint
high level power, transparent runtime.

Flint is a statically typed, compiled language designed around transparency. Write expressive, high-level code while understanding exactly what happens at runtime. Automatic memory management through DIMA, powerful composable entities, callables and persistent locals, and interoperability with C libraries make Flint practical for real-world projects.

Flint is in late beta. The language has stabilized with rare breaking changes. Try it out and share feedback!

Why choose Flint?

Flint stands out by combining high-level ergonomics with runtime transparency. Here's what makes it different:

Transparent Runtime

Unlike many high-level languages, you can always understand what your code is doing. High-level syntax maps directly to predictable, inspectable behavior you can reason about.

Declarative Composable Modules

Flint's unique DCMP paradigm combines the best of OOP and ECS. Build complex systems through composition of data and behavior, with compile-time dispatch and clear semantics.

Seamless C Interoperability

The Flint Interop Protocol (FIP) lets you use advanced C libraries like raylib without writing bindings. Use what you need from the C ecosystem effortlessly.

Automatic Memory Management

DIMA (Deterministic Incremental Memory Architecture) provides automatic, garbage collection-free memory management that you can understand and predict.

Static Compilation

Compile to optimized native code. Flint is designed to produce fast, predictable executables that perform well in real-world applications.

Comprehensive Learning Path

The Wiki provides a complete learning journey from beginner to expert. It is always up to date with every feature and rule explained, as Flint aims to be finite.

The Declarative Composable Modules Paradigm

DCMP is Flint's core innovation: a new programming paradigm that elegantly combines data composition with behavior. It is based on the core idea of separating data from behaviour, and then recombining them in a declarative manner. DCMP requires a different mindset than OOP, you might need to adjust your thinking to use it effectively.

Key Concepts

1
Data Modules Define what data your system contains. Data modules are reusable across many different func modules and entities.
2
Func Modules Define behavior that operates on specific data. Transparent about requirements and effects. Func modules also act like native interfaces.
3
Entities Compose data and behavior together deterministically. There are many more enttiy-specific features than shown here, they can be found in the Wiki.
4
Similar in use to Objects Entities can be used similar to objects in OOP languages, but they are not the same. DCMP is strictly composition-based so there exist no concepts of inheritance.

DCMP Example

use Core.print

// Define data
data Wings:
    u32 size;
    u32 flight_time;
    Wings(size, flight_time);

// Define behavior
func Fly requires(Wings w):
    def fly():
        print($"Flying for {w.flight_time} seconds\n");

// Compose into entity
entity Bird:
    data: Wings;
    func: Fly;
    Bird(Wings);

// Use entities like objects
def main():
    bird := Bird(Wings(10, 20));
    bird.fly();

Seamless C Interoperability

The FIP (Flint Interop Protocol) is a protocol-based communication library aiming to unify interop between languages. The Flint compiler communicates with specialized Interop Modules over that protocol, to enable native interop with other (compiled) languages. The C interop module is the only one working so far, but more will follow.

Small Raylib Example

// Include auto-generated FIP module aliased as 'rl'
use Fip.raylib as rl

// Const data is comptime-substituted
const data Col:
    u8x4 bg = u8x4(245, 245, 245, 255);
    u8x4 fg = u8x4(45, 45, 45, 255);

def main():
    rl.InitWindow(1280, 720, "Raylib Example");
    while not rl.WindowShouldClose():
        rl.BeginDrawing();
        rl.ClearBackground(Col.bg);
        rl.DrawText("Hello from Raylib!", 100, 200, 60, Col.fg);
        rl.EndDrawing();
    rl.CloseWindow();

Key Concepts

1
Protocol-Based Communication Each Interop Module is a master in it's own language, the Flint compiler does not need know about other languages at all.
2
Interop Compile Errors Through FIP the compiler can detect which functions or symbols are missing or nonexistent at parse-time. No more ambiguous "symbol not found" linking errors!
3
Auto-Generated Bindings The compiler auto-generates bindings for code from supported foreign languages for you.

Callables And Variable Persistence

In Flint, every function can be referenced as a callable and passed around as a value. By referencing functions as callables, its persistent local state is preserved across invocations. Through this, callables enable powerful patterns like counters, rate limiters, state machines, accumulators, and more. This all is possible thanks to Flints unique runtime which, again, aims to be as lean and transparent as possible.

Key Concepts

1
Functions as Callables When referencing a function, a callable instance is created. Callables are first-class values that can be passed around and invoked like regular functions.
2
Persistent Local State Callables preserve their persistent local state across invocations, allowing for stateful behavior without global variables. This local state is stored on a per-instance basis, so each callable instance has its own local state which is not shared with any other instance.
3
Regular Functions Persistent locals are just regular local variables for regular function calls and can be used as such. Flint does not differentiate between callables and regular functions at the lowest level, the same code is executed for both.
4
It's not static You may know the static keyword in languages like C++ or Java, persistent local variables are not the same. Persistent locals are not global variables, they exist on a per-instance basis.

Rate Limiter Example

use Core.print
use Core.time

def execute_function():
    print("Executed\n");

def execute_maybe(fn<> function) -> bool:
    persistent TimeStamp last = now();
    TimeStamp current = now();
    Duration elapsed = duration(last, current);

    if as_unit(elapsed, TimeUnit.S) < 1.0:
        return false;

    function();
    last = current;
    return true;

def main():
    fn<> task = ::execute_function;
    fn<fn<> -> bool throttled = ::execute_maybe;
    i32 c = 0;
    while c < 4:
        if throttled(task):
            c++;

Getting Started

Ready to explore Flint? Start with the comprehensive Wiki that teaches you everything from basics to advanced features.

📖

Read the Wiki

Follow the structured learning guides from beginner to expert. Learn the language fundamentals, core concepts, and advanced features.

🏗️

Build & Compile

Install Flint and start compiling programs. The compiler is written in C++ and is ready for real-world use in late beta.

💬

Join the Community

Connect with other Flint developers on Discord. Share ideas, ask questions, and contribute to shaping the future of the language.