Est. 2001 Advanced

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

Paradigm Multi-paradigm: functional, imperative, object-based, generic, with coroutines and CSP-style concurrency
Typing Static, strong, inferred, polymorphic with type classes
First Appeared 2001
Latest Version Release 2019.01.06 (6 January 2019)

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:

CompilerAckTakfp
Felix/clang3.716.23
Clang/C++3.956.29
Felix/gcc2.346.60
Gcc/C++2.256.25
OCaml2.938.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.

ReleaseDateNote
v1.1.6rc1 / rc26 and 13 Dec 2010Last conventionally numbered tags
2016.01.04-rc1 / rc2Jan 2016Start of a busy release year
2016.04.10-rc1 / rc210 Apr 2016Two release candidates same day
2016.07.12-rc112 Jul 2016Version stamped on the ReadTheDocs tutorial
2018.09.16Sep 2018Uniqueness types, subtyping, early kinding system
2019.01.066 Jan 2019Last dated release
msvc-win64 snapshot15 Nov 2021Windows 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

2001
The Felix project is registered on SourceForge on 3 June 2001, described as a "Felix programming language specifications and translator" and released into the public domain, with C++, OCaml and Python listed as its implementation languages
2010
The project moves from SourceForge to GitHub; the felix-lang/felix repository is created on 2 March 2010. Development had by then adopted fbuild, a Python 3 build system written by contributor Erick Tryzelaar
2010
Tags v1.1.6rc1 (6 December) and v1.1.6rc2 (13 December) are cut, the last tags to use conventional semantic-style version numbers before the project switches to date-stamped releases
2016
Three dated release series ship in a single year - 2016.01.04, 2016.04.10 and 2016.07.12 - cut as five release-candidate tags in all, alongside documentation published on ReadTheDocs as a set of separate manuals: language reference, tutorial, tools guide and library packages
2018
Release 2018.09.16 ships in September, tagged on 12 September, adding uniqueness types, subtyping and the beginnings of a kinding system
2019
Release 2019.01.06 ships on 6 January - the last dated release published on the project's GitHub releases page
2021
A Windows 64-bit MSVC snapshot build is published on 15 November, the final artefact posted to the releases page
2024
Skaller's last recorded burst of work lands in March and April - real-time allocators, a Felix interface to them, unification of coroutines and subroutines into a single continuation object, and real-time CSP procedure support - with the final commit dated 23 September 2024

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.

Language Influence

Influenced By

Running Today

Run examples using the official Docker image:

docker pull
Last updated: