Felix
An ML-style statically typed language that compiles to optimised C++, built by an Australian C++ committee veteran who wanted functional programming without giving up C and C++ libraries, and whose grammar lives in its own standard library.
Created by John Skaller
Felix is a statically typed, ML-influenced language that does not have a runtime of its own in any conventional sense. It compiles to C++ source, which your own C++ compiler then compiles and optimises a second time. The result sits in an unusual position: a language with type classes, pattern matching, garbage collection and coroutines, which nevertheless links against std::vector and std::shared_ptr as naturally as C++ does, because the objects it manipulates are C++ objects.
Its own tagline is “an advanced, statically typed, high performance scripting language with native C++ embedding” - a description that packs three ideas that do not usually appear together. It has been characterised - in a widely shared Hacker News submission title, among other places - as being to C++ roughly what F# is to C#: a functional language sharing the host platform’s object model rather than replacing it.
Felix was substantially the work of one person, John Skaller, over more than two decades. It never acquired a corporate sponsor, a package ecosystem, or a user base of meaningful size. What it acquired instead was depth - a compiler with whole-program optimisation, a user-extensible grammar, a coroutine system, and documentation running to several book-length manuals, all maintained by a single author until the commits stopped in September 2024.
History & Origins
A C++ committee veteran with a list of complaints
Skaller came to language design from the inside of C++. Under the name John Max Skaller he submitted a long run of papers to the C++ standards committee (WG21) in 1993 and 1994, on binary literals, in-class initialisers and nested functions in 1993, and in 1994 on template facilities, constant expressions, checked numeric conversions, template specialisations, pointers to members, type-safe printf, enhanced unions and implicit new-style casts. The committee-paper archives reportedly list his address in Glebe, New South Wales, Australia.
Before Felix he had also written Interscript, a literate-programming tool that used Python as its client scripting language and was itself written as a literate Python program. Interscript was reportedly more than a side project as far as Felix is concerned: early versions of Felix are said to have used Interscript to generate their source files, a dependency that was later removed.
Both threads show up in the language. Felix’s attitude to C++ is not hostile - it is the attitude of someone who knows exactly which parts of C++ are worth keeping (the object model, the libraries, the optimising back ends) and which parts he would rather write in ML.
2001
The Felix project was registered on SourceForge on 3 June 2001, licensed into the public domain and categorised under code generators and compilers, with C++, OCaml and Python listed as its implementation languages. That last detail is the whole architecture in miniature: the Felix compiler is an OCaml program that emits C++, driven by Python tooling.
The project stayed on SourceForge through the 2000s, with felix-lang.org as its home page, and moved to GitHub in 2010; the felix-lang/felix repository dates from 2 March 2010. By that point the build was driven by fbuild, a Python 3 build system written by contributor Erick Tryzelaar, who would later join the Rust core team.
Design Philosophy
The C++ object model, kept deliberately
Most languages that generate C or C++ treat the output as an assembly language - an implementation detail the programmer should never see. Felix does the opposite. It uses the C/C++ object model as its own, which is what makes its binding sublanguage possible: a Felix type can simply be a C++ type, declared by writing the C++ spelling down.
// required headers
header vector_h = '#include <vector>';
header memory_h = '#include <memory>'
requires package "cplusplus_11"
;
// a Felix type that is literally a C++ type
type vector[T] = "::std::shared_ptr<::std::vector<?1>>"
requires vector_h, memory_h
;
ctor[T] vector[T] : unit = "::std::make_shared<::std::vector<?1>>()";
proc push_back[T] : vector[T] * T = "$1->push_back($2);";
var v = vector[int]();
v.push_back 42;
The ?1 and $1 placeholders are substitution points into emitted C++. Templates, smart pointers and STL containers bind directly, without a foreign-function interface, without marshalling, and without a wrapper generator.
Performance as an explicit goal
The project’s stated aim is blunt: “The aim is to run faster than C.” The mechanism is whole-program analysis with aggressive inlining, plus high-level transformations such as parallel assignment and self-tail-call elimination, after which the generated C++ is handed to a production optimising compiler for a second pass.
The project publishes its own comparison table, giving times on two microbenchmarks - Ack (Ackermann’s function) and Takfp (a floating-point variant of the Takeuchi function), both long-standing recursion-heavy benchmarks:
| Compiler | Ack | Takfp |
|---|---|---|
| Felix/clang | 3.71 | 6.23 |
| Clang/C++ | 3.95 | 6.29 |
| Felix/gcc | 2.34 | 6.60 |
| Gcc/C++ | 2.25 | 6.25 |
| OCaml | 2.93 | 8.41 |
Read these carefully. The published table gives no hardware, operating system, compiler version, benchmark parameters or run methodology, so the numbers are best treated as the author’s own illustrative figures rather than an independently reproducible benchmark. Read on their own terms they show something narrower than the tagline: on Ack Felix beats Clang/C++ (3.71 vs 3.95) but loses to Gcc/C++ (2.34 vs 2.25), and on Takfp the four C++ figures sit within about 6% of each other. The honest claim supported by the table is that Felix lands in the same performance class as hand-written C++ on recursion-heavy microbenchmarks - which, for a garbage-collected language with type inference and pattern matching, is the interesting result anyway.
The grammar is a library
Felix’s most unusual structural decision is that its syntax is not built into the compiler. The parser is built on dypgen, a GLR parser and lexer generator for OCaml that produces self-extensible parsers: a grammar action can add new rules to the grammar currently being parsed, and those additions can be scoped to a delimited region of the input.
Felix uses this to define the bulk of its own statement and expression syntax in library files written as EBNF grammar rules with action codes in R5RS Scheme, loaded at compile time. Users can extend the grammar the same way, defining domain-specific sub-languages (DSSLs) that are parsed as first-class syntax rather than as strings passed to a runtime interpreter.
The clearest example ships with the language: the chips and circuits DSSL, which gives coroutines a syntactic model as chips and the topology of channels connecting them as circuits.
Key Features
ML-style types over a C++ substrate
// hello.flx
println$ "Hello World";
That file runs directly with flx hello.flx. Behind the one-liner is a full ML-family type system:
- Parametric polymorphism with type inference
- Type classes for ad-hoc polymorphism, alongside a module system
- Discriminated unions and pattern matching
- First-class, lexically scoped closures and higher-order functions
- Garbage collection, on top of C++ objects
- Overloading, generics, and a distinction between functions (
fun) and procedures (proc)
The autobuilder
The flx driver is what makes the “scripting language” half of the description defensible. Running flx hello.flx compiles, caches and executes without a makefile or a single compiler switch, with dependency checking for both Felix and C++ sources. Library and header discovery goes through flx_pkgconfig, a database of *.fpc files keyed by abstract in-language names. The experience is closer to running a Python script than to driving a C++ build.
Coroutines, fibres and channels
Concurrency in Felix is layered rather than singular. Coroutines provide synchronous context switching with control exchanged explicitly - the documentation calls the switches “ultra-fast”, though no published measurement backs the phrase; fibres exchange control through channels, in the CSP tradition. Above that sit pre-emptive threads and asynchronous event handling for I/O and networking. Skaller’s final commits in 2024 were still working this seam - unifying coroutines and subroutines into a single continuation object, and adding real-time CSP procedure support.
Text processing built in
Regular expressions are provided by binding Google RE2, and the language has built-in support for context-free parsing - which, given that the compiler’s own grammar is a library, is less surprising than it first sounds. Optional packages cover SDL2 for the graphics and GUI library, and GNU GMP and GNU GSL for arbitrary-precision and scientific numerics.
Evolution
Felix’s release history splits cleanly in two. Through 2010 it used ordinary version numbers, ending at v1.1.6rc2 in December 2010. Everything after that is date-stamped: 2016.01.04, 2016.04.10, 2016.07.12-rc1, 2018.09.16, 2019.01.06.
| Release | Date | Note |
|---|---|---|
| v1.1.6rc1 / rc2 | 6 and 13 Dec 2010 | Last conventionally numbered tags |
| 2016.01.04-rc1 / rc2 | Jan 2016 | Start of a busy release year |
| 2016.04.10-rc1 / rc2 | 10 Apr 2016 | Two release candidates same day |
| 2016.07.12-rc1 | 12 Jul 2016 | Version stamped on the ReadTheDocs tutorial |
| 2018.09.16 | Sep 2018 | Uniqueness types, subtyping, early kinding system |
| 2019.01.06 | 6 Jan 2019 | Last dated release |
| msvc-win64 snapshot | 15 Nov 2021 | Windows 64-bit binary snapshot |
Development did not stop with the last release - it simply stopped being packaged. The repository accumulated roughly 8,500 commits, and work continued in the tree for another five years after 2019, with the final push on 23 September 2024.
The documentation followed the same trajectory: Felix is split across at least four separate ReadTheDocs projects - a documentation master and language reference at felix.readthedocs.io, plus a tutorial, a tools guide and a library packages reference - a documentation-to-users ratio that few languages have ever matched.
Officially supported build platforms, per the project’s own README, are Linux, macOS and Windows (the latter via Visual Studio, with build instructions maintained on the project wiki), plus a Nix shell environment and an Arch Linux PKGBUILD. Building from source requires Python 3, OCaml 4.06.1, and a C++ compiler (g++, clang++ or MSVC).
Current Relevance
Felix is dormant. There has been no release since January 2019, no artefact on the releases page since the Windows snapshot of November 2021, and no commit since September 2024. The repository is not archived, and the mailing list address still exists, but the language is in practice a single-author project whose single author has stopped.
Its GitHub footprint - a little over 800 stars and around 47 forks as of mid-2026 - describes the shape of its audience accurately: a steady trickle of people who found it interesting, periodically refreshed when it surfaced on Hacker News in 2013 and 2014, and very few who shipped anything with it. It does not appear in the TIOBE index, RedMonk’s language rankings or Stack Overflow’s developer surveys, and there is no public record of significant commercial adoption.
The one genuinely low-friction thing about it is the licence: Free For Any Use (FFAU) / Public Domain. Anyone who wants to fork, vendor, relicense or strip-mine Felix for ideas can do so without asking.
Why It Matters
Felix is worth knowing about for a set of ideas it worked out carefully, most of which the industry arrived at later by other routes.
It refused the FFI tax. The standard bargain for a new language is that talking to C++ costs you a wrapper generator, a marshalling layer, and a permanent seam between “our objects” and “their objects”. Felix declined the bargain by adopting the C++ object model wholesale and letting types be declared by writing their C++ spelling. Two decades on, zero-overhead C++ interop remains an unsolved problem for most languages - Rust and Swift both invest heavily in it, and neither gets templates and STL containers as cheaply as Felix’s binding sublanguage does.
It put the grammar in the library. Extensible syntax is an old idea that usually arrives as a macro system bolted onto a fixed grammar. Felix built on a self-extensible GLR parser and defined most of its own surface syntax in library files, so user-defined sub-languages are parsed by exactly the same mechanism as the built-in ones. That is a stronger position than almost anything outside the Lisp family, and Felix reached it while keeping C-family syntax.
It treated code generation to C++ as a design choice rather than a shortcut. Compiling to C is normally a bootstrapping stage a language grows out of. Felix’s argument was that the second optimising pass is worth keeping permanently, because the C++ compilers are where the world’s optimisation effort actually goes. The benchmark table is more modest than the “faster than C” slogan, but the underlying claim - that a high-level language sitting on top of a production C++ back end can land in C++’s performance class - holds up.
And it is a case study in the limits of solo language design. Felix is technically deeper than many languages with a thousand times its user count. What it never had was a second maintainer, a killer application, or a company depending on it. When one person stopped committing, the language stopped. That is not a criticism of the work; it is the most reliable lesson the project has to offer about what keeps a language alive, and it is not the type system.
Timeline
Notable Uses & Legacy
dypgen
The self-extensible GLR parser generator for OCaml that Felix uses to implement its user-extensible grammar. A fork is maintained under the felix-lang GitHub organisation, and Felix appears to be one of the more substantial consumers of dypgen's adaptive-grammar capability.
fbuild
A Python 3 build system written by Felix contributor Erick Tryzelaar - later a member of the Rust core team - and used to build the Felix compiler itself. It was developed alongside Felix and hosted under the same organisation.
Felix standard library grammar
Felix's own syntax is not hard-coded in the compiler; the bulk of the grammar is defined in Felix library files and loaded at compile time. The standard library is therefore both the language's biggest codebase and the live demonstration of its domain-specific sub-language machinery.
C and C++ library bindings
The distribution ships bindings for real C/C++ libraries through its binding sublanguage - Google RE2 for regular expressions, SDL2 for the graphics and GUI library, and optional GNU GMP and GNU GSL support - which serve as the project's practical proof that C++ libraries embed with little or no glue code.
Arch Linux AUR package
Felix is packaged for Arch Linux through a PKGBUILD shipped in the source tree and published in the AUR, the closest the language came to distribution-level packaging.