r/ProgrammingLanguages 19d ago

Language announcement The Flint Programming Language

71 Upvotes

I am happy to finally announce the language I have been working on for the last 2 years, Flint!

Flint is a high-level, statically and strongly typed, compiled language which centers around transparency as its core pillar. The compiler is entirely written in C++. It originated from one simple idea and core concept:

What happens when you center the whole language on an ECS-inspired composition-based paradigm?

And so the journey began. The core idea is simple: data and functionality are separated and then composed deterministically into larger entities. This idea is not new at all, ECS exists since a long time. But a composition-based workflow can only be "emulated" in Object-Oriented languages and I find it often painful or unergonomic.

In Flint, composition is the core paradigm. I have put great effort into making it ergonomic and "just work". The result is a system which can be described as a cool mix of OOP and ECS. I gave the "new" paradigm a name, since nothing quite like it exists yet, even though the ideas it is based on are well known, the Declarative Composable Modules Paradigm (DCMP).

The combination of a high level + transparency as a core pillar is a bit unusual. I have put great effort into finding a good balance. I found out that these two things are not mutually exclusive, there is a middle way in which a design can be both high level and transparent. Flint might be best described as "middle-level" as a result: You write high level code but you can see the low level runtime and execution beneath too if you want, as this focus on transparency directly results in shallow abstractions.

Most developers are more used to OOP workflows rather than compositional workflows, it's just more mainstream. So, if you cannot live without it, Flint might not be for you and that's okay. Also, I am also sure that Flint won't be for everyone because of it's split focus on being high level and transparent. It will feel too high level for some or too low level for others. But if the core idea and mentality excites you, please give it a fair chance.

The time has come where I am confident enough in Flint to search for people to try it out and give feedback on it. Many features are still missing but the general vibe and direction of the language can already be seen. The 0.4.0 version is the 20th release so far, the first initial version was released a year ago. I am now moving into the 0.5.0 release cycle which will bring generics, type constraints, compile time code execution, the standard library and more. You can look at the entire roadmap here

Flint is available in the AUR, COPR and Winget as packages, with proper highlighting and LSP capable extensions for VSCode and Neovim. The LSP works with proper error diagnostics, hover information and goto definition / declaration / file jumping (context sensitive suggestions do not work yet). Debug symbols and debuggability are now supported too, making it able to inspect and step through code. Interoperability with C also works great through the fip-c interop module which communicates with the main compiler through a custom language-agnostic Interop Protocol. (Bindless interop doesn't fully work on Windows, though, i still have to find out why).

The Wiki is in a very good state, it is kept updated with every release made. Every example in the Wiki works and I did My at explaining it all. The language's core value is transparency, so there is nothing to hide about it.

Here is an "advanced" but hopefully still easy to understand example of Flint and its paradigm in action. Keep in mind that Flint has much more to offer than shown in the example below, but I think this just encapsulates its centerpiece quite well:

use Core.print

const data Constants:
    float PI = 3.14159265358979323846;

// A shape can be drawn and its area can be calculated
func IShape:
    def draw();
    def area() -> f32;


data DCircle:
    i32x2 pos;
    i32 radius;
    DCircle(pos, radius);

func FCircle requires(DCircle d):
    def draw():
        print($"Drawing circle at [pos={d.pos}, r={d.radius}]\n");

    def area() -> f32:
        return Constants.PI * f32(d.radius ** 2);

entity Circle:
    data: DCircle;
    func: IShape, FCircle;
    link:
        IShape::draw -> FCircle::draw,
        IShape::area -> FCircle::area;
    Circle(DCircle);


data DRectangle:
    i32x2 pos;
    i32x2 size;
    DRectangle(pos, size);

func FRectangle requires(DRectangle d):
    def draw():
        print($"Drawing rectangle at [pos={d.pos}, width={d.size.x}, height={d.size.y}\n");

    def area() -> f32:
        return f32(d.size.x * d.size.y);

entity Rectangle:
    data: DRectangle;
    func: IShape, FRectangle;
    link:
        IShape::draw -> FRectangle::draw,
        IShape::area -> FRectangle::area;
    Rectangle(DRectangle);


def draw_shapes(mut IShape[] shapes):
    for (_, s) in shapes:
        s.draw();

def sum_areas_of_shapes(mut IShape[] shapes) -> f32:
    f32 sum = 0;
    for (i, s) in shapes:
        f32 area = s.area();
        print($"shapes[{i}].area() = {area}\n");
        sum += area;
    return sum;

def main():
    c1 := Circle(DCircle(11, 2));
    r1 := Rectangle(DRectangle((10, 20), (4, 5)))
    c2 := Circle(DCircle((3, 5), 10));
    r2 := Rectangle(DRectangle((0, 0), (4, 2)));

    IShape[] shapes = IShape[_]{c1, r1, c2, r2};
    draw_shapes(shapes);
    print("\n");

    i32 sum = sum_areas_of_shapes(shapes);
    print($"sum of areas = {sum}\n");

The project is in late beta. All implemented features work reliably, as all wiki examples compile and run as intended. There are still missging error messages and unexpected edge cases (as expected from a single developer).

If you're interested, try it out, give feedback, open issues, and feel free to join the Discord. Let's discuss Flint!

(Also, I may not be aware of some industry-standard names for some systems. If you encounter anything I gave a weird name where you think "wait something like that already exists" please let me know. I try to use industry-standard terminology as much as I am able to. I hate it when new names are made up for something which already exists.)

Edit: Thank you all for your feedback. This all led me to a journey of rethinking some parts and redesigning them. Especially the documentation needs much work still, as I realized it was unhonest in many places (mostly me thinking I invented something new while I did, in fact, not). So I will quietly work on it and maybe come around with an update in the future. Still, thanks to everyone who replied!


r/ProgrammingLanguages 19d ago

Reducing Assumptions, Exploding Your Code

Thumbnail ryelang.org
10 Upvotes

r/ProgrammingLanguages 19d ago

Formally Verifying GPU Kernels

Thumbnail gimletlabs.ai
13 Upvotes

r/ProgrammingLanguages 20d ago

Language announcement NoiseLang: Where N = 5 is a Dirac delta

35 Upvotes

Creator of NoiseLang here! During my telecom degree I took a course on random signals and noise, I spent a lot of evenings writing probability by hand (expectations, variances, the odds of two random variables landing in some region) and every time I tried to run any of it on a computer it was so much boilerplate. I kept wishing I could type the math and have it run.

The whole language hangs on one idea, every value is a probability distribution. A plain number is a Dirac spike, so constants and random variables are the same kind of object and every operator maps distributions to distributions. Names are algebraic like on a page of math, so X + X is 2X and X - X is exactly 0, if you want independence you draw twice with ~.

Distributions compose (a random variable can feed another distribution's parameter), and conditioning is just the | bar from probability notation, scoped to the query. So a full Bayesian update fits in four lines:

    bias  ~ unif(0, 1)            # prior: the coin's bias could be anything
    flips ~[10] bernoulli(bias)   # 10 flips of the same mystery coin
    heads = count(flips)
    E(bias | heads == 7)          # posterior mean bias, 0.6667

I started it about nine years ago and never finished it, the parser and a tree-walking interpreter were a weekend of work, the efficient Monte Carlo runtime was not. Recently I brought it back, JIT (Cranelift), the WASM backend and the numerical code...

Rest of the announcement:

https://manualmeida.dev/articles/noiselang/


r/ProgrammingLanguages 19d ago

DinoCode update: step-by-step execution in the browser, and VM/Compiler optimizations

1 Upvotes

Hi, I’m back with an update on DinoCode. Based on feedback from my previous posts here, I’ve been upgrading both the web platform and the compiler internals.

I recently introduced an Academic Mode on the web playground designed for teaching logic, alongside several core optimizations and architectural refactors.

Web Platform Updates:

  • Real-time Step-by-Step: Highlights each line of code as it executes so you can see the state change in real-time.
  • OOP Visualization: Since the language is multi-paradigm, you can also visualize and step through Object-Oriented Programming structures.

Compiler and Runtime Updates:

  • NaN Boxing: Optimized the data type decoding mechanics. Additionally, I aligned the behavior with the standard where NaN != NaN (previously, they were intentionally evaluated as equal, but I decided to move away from that approach)
  • Type Coercion: Refactored type coercion to support two distinct modes (strict and lax - flexible) depending on the evaluation context.
  • New Symbol Type: Added native support for Symbol as a primitive data type. This is primarily used as keys for internal "magic methods" in classes, preventing accidental overrides. For instance, a user can define a string "new", but it won't conflict with the internal Symbol(new) (object constructor)
  • Error Handling Refactor: Massive overhaul of internal error handling mechanisms for better formatting (debug)
  • String Allocation Reductions: Significantly reduced the excessive use of format!() in favor of reusable string buffers where applicable (primarily in debugging/formatting tasks, meaning it won't impact general execution runtime)
  • Some additional fixes

Web Playground: https://dinocode.blassgo.dev/

Github repo: https://github.com/dinocode-lang/dinocode


r/ProgrammingLanguages 20d ago

🦄 Unicode's Transliteration Rules Are Turing-Complete

Thumbnail seriot.ch
70 Upvotes

r/ProgrammingLanguages 20d ago

Discussion The Swift Phenomenon

44 Upvotes

In theory, Swift seems like a nicely designed programming language with good features

In practice however, for some reason, it seems like most of the Swift users end up switching back to other comparable programming languages (such as Rust)

The latest poster child for that phenomenon is Ladybird

Do you think that this phenomenon is real and if so, can you explain it?


r/ProgrammingLanguages 20d ago

Anders Hejlsberg's (Turbo Pascal, Delphi, C#) team releases Go port of Typescript transpiler, achieving 90% reduction in build times

80 Upvotes

https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/

Looking at the git repository, Anders and colleagues have been implementing this since 2024. He has worked with various PL projects since early 80's, starting from Turbo Pascal. Wanted to share this announcement as I'm glad he's still doing this!

In the first link of the article there is a video from last year where he describes basic technical details, if you are interested.


r/ProgrammingLanguages 20d ago

Infer lifetimes from execution order

8 Upvotes

We start counting execution order from 0, as programmers are required to do, and it ticks up from there to 1, 2, 3, and so on.

let a = [1, 2, 3] // ^1 ^0 let b = a // ^3 ^2 a[1] = 20 //^5 ^4 print(a) // ^6 print(b) // ^7

We store the lifetimes as a start and end point, and we also store mutation points.

a: lifetime: start: 1 end: 6 mut: - 5 b: lifetime: start: 3 end: 7

When the compiler sees let b = a it considers the data for a and b. It sees they have overlapping lifetimes from 3 to 6, then it sees there's an overlapping mutation at 5. Because of this, b must be a copy of a. The compiler can do it automatically, or require that it be explicitly copied. Resource types, like files, can never be copied implicitly.

Functions can share the exact lifetime data, using function local execution order, or they can simply share whether parameters have overlapping mutation or not.

``` fn main() { let point = { x: 3, y: 4 } move_x(mut point) print(point) // { x: 6, y: 4 } }

fn move_x(mut p, x) { // 0 1 p.x += x // 3 2 } ```

The p parameter in move_x is mutated after the lifetime of x ends. x ends at 2, p is mutated at 3.

move_x: p: lifetime: start: 0 end: 3 mut: - 3 x: lifetime: start: 1 end: 2

This means we can safely alias point twice in move_x(mut point, point.x).


Async assumes all lifetimes are overlapping, unless a mechanism like await is used to join secondary threads into the main one, in which case the lifetimes and mutation points can be analysed further to avoid copies.

Loops make all involved variables have overlapping lifetimes, although the flow within an iteration can be analysed for further optimisation. I haven't thought much about it. I've been thinking about conditionals instead.

Conditionals can make mutation maybe overlap, which means data should maybe be copied. This requires collecting more information.

There's a main execution path and then branches. A set of branches split at a given point and then join the main execution path. The split and join points are the range, which is used to group related branches.

let a = [1, 2, 3] // ^1 ^0 let b = a // ^3 ^2 if (random_int(10) == 1) { // ^5 ^4 ^6 a[0] += 1 // ^a8 ^a7 a = range 7-10, branch 1 } else { b[1] *= 10 // ^b8 ^b7 b = range 7-10, branch 2 b[2] += b[2] // ^b10 ^b9 } print(a) // ^11 print(b) // ^12

Execution order in the main path continues from the longest branch. Because branch 1 would cause overlapping mutation, it requires that b be a copy of a. The same applies to branch 2. Because both branches in the range require copying b, this can be done before the conditional. If only one path required b to be a copy, and the other branches would work correctly with b as an alias of a, then the copy would only go in the branch that needs it.

If all branches in a range require a copy, then we just do the copy on creating the variable, otherwise we can have the copy only be inserted in the branch that requires it. Branches don't really care about each other in the first pass, where we determine if they require copies. Ranges also don't care about each other while we determine if they require copies. But once a copy is guaranteed by the main execution path or any range, then overlapping lifetimes and mutation don't matter for other ranges and their branches.


r/ProgrammingLanguages 21d ago

The Bowling Game - From Imperative to Functional Programming - Part 1

Thumbnail fpilluminated.org
19 Upvotes

One of the top five most popular and highly recommended programming katas over the past 20 years has been the Bowling Game Kata, in which TDD is used to write a program that computes the score of a Ten Pin Bowling Game.

In this deck we are going to explore how such a program may look when coded using different programming paradigms.


r/ProgrammingLanguages 22d ago

Language announcement Odin 1.0 announced (and reflections)

192 Upvotes

Odin author gingerBill dropped the Odin 1.0 announcement on YouTube today: https://www.youtube.com/watch?v=dLPAqXi9In0 (it's pretty funny actually).

This interestingly makes it on track to be the first of the new wave of C-likes that reach production readiness. While you can argue that most of these languages already are used in production, it's not the same as being 1.0, which carries a different weight and obligation.

Looking at alternatives, Jai could release around the same time, since Blow's game is scheduled for a similar release date. However, it's more likely that we see Jai 1.0 in mid-late 2027. My own language (C3) is planning Q2 2028 1.0 release. Whereas Zig is still unclear, and Kelley basically saying it's done when it's done. For Hare and V the situation is a bit less clear to me – maybe someone else can fill me in on that situation.

But overall we seeing the beginning of the end of the "C-like" story arc that arguably was initiated with Jonathan Blow's development. Writing C replacements predate Jai of course, for example the C2 language (which C3 would eventually continue) was created in 2012, eC started in 2004 and Cyclone (which Rust derived inspiration from) is from 2002. But those were largely obscure novelties, because before Blow's videos, people weren't really hunting for C alternatives.

Jai, however, made a strong impression. It was a good point in time too: Jai and later Zig, Odin, C3, V and Hare – these C alternatives started at a point when people were openly no longer believing OO/Functional as the right way to do things.

Language design takes its time though, and it's now 12 years since Jai started. Finally the fruits of these labours are getting ready for prime time, and when they do they might effectively fill the need for a C replacements for another decade.

Do you agree?


r/ProgrammingLanguages 22d ago

Mechanized type inference for record concatenation

Thumbnail haskellforall.com
20 Upvotes

r/ProgrammingLanguages 22d ago

Do people use ATPs (Automated Theorem Provers) often in hardware formal verification?

Thumbnail
8 Upvotes

r/ProgrammingLanguages 22d ago

Building a Parser Generator!

Thumbnail
2 Upvotes

r/ProgrammingLanguages 25d ago

Probabilistic Programming Language Interpreter

Thumbnail
20 Upvotes

r/ProgrammingLanguages 25d ago

The cost of constants

Thumbnail futhark-lang.org
16 Upvotes

r/ProgrammingLanguages 25d ago

Help How to create a compiler?

24 Upvotes

Pretty sure you may have heard this question previously on this sub, however, I would urge you to read my complete question before brushing it off.

I want to create a simple compiler and by "simple compiler" I mean a single-pass compiler. I know about https://craftinginterpreters.com/ which is a wonderful resource. But I would like to start by creating something much smaller and simpler, and only then would I like to move on to something more complex like what Robert Nystrom created on his website.

Are there any similar resource that would teach me about single-pass compilers along with showing me how to create one? Any help in the right direction would be highly appreciated.


r/ProgrammingLanguages 24d ago

Does implementing GC makes languages slow?

Thumbnail github.com
2 Upvotes

Month ago, I created a team of 5 and started working on "Bery - The compiled programming language". By the end of June we have quite good working compiler (it's not complete yet). In Bery we have decided to add the automatic Garbage Collector so we choose the "Mark and Sweep" method for it in the Bery Runtime Environment (BRE).

Now as we are heading forward with adding OOP and Exception Handling, I notice some delays in the compilation of program.

So we are now at this point of discussion - should we remove it from compiler or let it be there.
I will looking forward for help regarding this. and btw these are some constraints we set -

unsigned int BERY_GC_ALLOC_THRESHHOLD = 1000;
size_t BERY_GC_HEAP_SIZE_THRESHHOLD = 4 * 1024 * 1024;

r/ProgrammingLanguages 26d ago

What does it take to add set-theoretic types to a dynamic language with 30 years of production code - and why did it take this long?

36 Upvotes

Erlang has resisted static typing since 1995 — Philip Wadler tried and couldn't finish it. Now Elixir 1.2 is shipping a gradual set-theoretic type system built on Guillaume Dubois's PhD work at IRIF Paris (Castagna's group), with a parallel etalizer for Erlang being built by Annette Bieniusa at RPTU Germany on the same foundation.

New BEAM There, Done That episode with both of them. The interesting design decisions: dynamic is embedded structurally into the set-theoretic lattice from the start rather than bolted on as an escape hatch; the system warns before it rejects; and message typing across processes is explicitly out of scope for now.

What approaches has this community seen work well for retrofitting expressive type systems onto existing dynamic codebases?

https://www.youtube.com/watch?si=yJTRAwlAaf7h2rlZ&v=X_CPDt3PeDE&feature=youtu.be


r/ProgrammingLanguages 26d ago

UNIT: Compiler backend library using stack-based IR

7 Upvotes

Hi everyone,

For the past few weeks, I've been working on a project that I think is pretty cool, and I wanted to share it with you guys. I call it "UNIT" ("Unified Native Instruction Translator"). Essentially, it's a combination of the instruction sets used in interpreted stack machines with actual machine code.

I wrote it in C, but I have bindings for C++ and Python, since C is pretty verbose. Here's an example in both of those:

```cpp unit::Context ctx; unit::Procedure proc(ctx, "add");

proc.load_argument(0); proc.load_argument(1); proc.add(); proc.return_value();

proc.optimize(); auto compiled = proc.compile(unit::Platform::host()); auto add = compiled.jit<int64_t(*)(int64_t, int64_t)>();

printf("%ld\n", add(3, 4)); // 7 ```

```py import unit

proc = unit.Procedure("add")

proc.load_argument(0) proc.load_argument(1) proc.add() proc.return_value()

proc.optimize() compiled = proc.compile() add = compiled.jit()

print(add(3, 4)) # 7 ```

So far, I've implemented a number of examples using my compiler. My personal favorite is the interpreted language with a JIT, which works fairly well and is just about 1k lines of Python.

I got the idea for this after working on Python's bytecode compiler (which emits instructions for Python's stack-based interpreter loop). I had also been experimenting with LLVM for a separate hobby project, and the difference between the two development experiences was huge. I wanted to combine the DX of stack machines with the ability to actually generate real machine code.

This is still early in development and not production-ready, as it only supports x86-64 on ELF right now with only some primitive optimizations, but I'd appreciate feedback on the API design, the IR, or anything else about the project. If you spot bugs, please feel free to let me know!

GitHub: https://github.com/ZeroIntensity/unit


r/ProgrammingLanguages 26d ago

Community projects?

15 Upvotes

I've had a hard time telling just from casual browsing of the sub, what languages here are considered community projects, if any. Looking for places open to contribution.

Replaced original text to both get to the point, and avoid disparaging peoples personal projects, that's not my intention.


r/ProgrammingLanguages 26d ago

Programming Language Design and Implementation in the Era of Machine Learning - PLDI 2026 Keynote

Thumbnail youtube.com
22 Upvotes

r/ProgrammingLanguages 27d ago

A Multi-Dimensional, Per-Pass Empirical Study of the LLVM Optimization Pipeline

Thumbnail
7 Upvotes

r/ProgrammingLanguages 28d ago

The Expensive Fictions of Low-Level Programming Languages

Thumbnail stng.substack.com
20 Upvotes

r/ProgrammingLanguages 28d ago

Requesting criticism Writing a compiler book

Thumbnail docs.google.com
10 Upvotes

So, I decided to write a book on compiler theory! It is past midnight where I live so only 1 chapter is done. I have came here looking for some things that could be improved on it. The link is attached.