The language

ErnosPlain

Code that reads like instructions, not cryptic symbols — yet compiles to C and runs at native speed. Statically typed, memory-safe, and self-hosting: its compiler is written in itself.

Syntax

Plain English

define add with a and b: — no braces, no semicolons.

Speed

Compiles to C

Emitted C, then clang -O2. No runtime tax.

Safety

Owned & checked

Type inference + a borrow checker catch errors before they run.

Proof

Self-hosting

The compiler compiles itself. 51/51 conformance tests pass.

~40klines (Rust + self-hosted)
5.8kcompiler, in ErnosPlain
51/51conformance tests
9codegen backends
24stdlib modules

Run it

The playground

Edit the code and press Run. This isn't a video — it's a real ErnosPlain interpreter executing in your browser.

And here's the twist: that interpreter is itself written in ErnosPlain, compiled to the browser by the Ernos compiler. The language is running itself.

your program · .ep
output

          

Live REPL

A console of your own

A persistent session — set a variable or define a function on one line, use it on the next. Enter runs · Shift+Enter for a new line · Tab indents.


A real program

Play a demo: the RPG battle

This isn't a toy. It's one of ErnosPlain's shipped demos — rpg_battle_system.ep, 362 lines — compiled to JavaScript by the very same Ernos compiler that builds it to native C. It exercises the hard parts of the language at once: structs, a trait with implementations for three types, a choice enum wrapping them, and dynamic dispatch over a mixed party.

Hit Fight — a party of two takes on two monsters. Damage and 20% criticals are randomised, so every battle plays out differently. Run it a few times.

Press Fight to run the battle. The same code compiles to native C — here it's running as JavaScript, in your browser.

Why plain English

The same function, three languages

ErnosPlain compiles to the same machine code as C — it just doesn't make you read like a machine to get there.

ErnosPlain reads aloud
define factorial with n returning Int:
    if n is less than 2:
        return 1
    return n times factorial(n minus 1)
Rust symbols
fn factorial(n: u64) -> u64 {
    if n < 2 { 1 }
    else { n * factorial(n - 1) }
}
C symbols
unsigned long factorial(
        unsigned long n) {
    if (n < 2) return 1;
    return n * factorial(n - 1);
}

Under the hood

From plain English to native code

No interpreter at runtime, no VM. Every .ep file walks the full compiler pipeline down to an optimised native binary.

source .ep lexer parser type inference borrow checker optimizer C codegen clang -O2 native binary

The compiler that does all this is written in ErnosPlain itself — it compiles its own source. The playground above is the same idea in miniature: an ErnosPlain interpreter, authored in ErnosPlain, running in your browser.


A tour of the language

Variables & functions
define greet with name returning Str:
    return f"Hello, {name}"

set who to "world"
display greet(who)
Choices & loops
set i to 1
repeat while i is less than 5:
    if i % 2 equals 0:
        display "even"
    else:
        display "odd"
    set i to i plus 1
Structures
define structure Point:
    field x as Int
    field y as Int

set p to create Point:
    x is 3
    y is 4
Choice & pattern matching
define choice Shape:
    variant Circle with r as Int
    variant Square with s as Int

check shape:
    if Circle with r:
        return r times r
    if Square with s:
        return s times s

The playground supports a procedural subset (variables, functions, recursion, conditionals, loops, lists, strings, f-strings). The full language adds structures, choice/pattern-matching, traits, closures, a borrow checker, 24 stdlib modules, and FFI — all compiled to native binaries.