A compiled language with plain English syntax, Hindley-Milner type inference, ownership-based memory safety, and C-level performance.
Ernos is a compiled, statically-typed, memory-safe programming language that reads like plain English. It compiles to optimized native binaries via C with performance equivalent to hand-written C code.
define factorial with n as Int returning Int:
if n < 2:
return 1
return n * factorial(n - 1)
define main:
display "Factorial of 20:"
display factorial(20)
return 0
No curly braces. No semicolons. No noise. Just code that reads like instructions.
| Feature | Ernos | Rust | Java | Python |
|---|---|---|---|---|
| Readability | ✅ Plain English | ❌ Symbolic | ❌ Verbose | ✅ Clean |
| Type Safety | ✅ HM Inference | ✅ Full | ✅ Full | ❌ Dynamic |
| Memory Safety | ✅ Ownership + GC | ✅ Ownership | ❌ GC only | |
| Performance | ✅ C-level | ✅ C-level | ❌ Interpreted | |
| Compile Target | Native binary | Native binary | JVM bytecode | Interpreted |
| Self-Hosting | ✅ | ✅ | ❌ | ❌ |
Ernos compiles to C, then to a native binary via clang -O2. The generated code has no interpreter overhead — it runs at the same speed as equivalent C.
- Hindley-Milner type inference — types are inferred even without annotations
- Enforced type checking — type errors stop compilation
- Ownership & borrowing analysis — use-after-move, move-while-borrowed detection
- Send/Sync safety — borrowed references cannot be sent to threads
define foo with x:
display x + 1 # type checker infers x must be Int
return 0
define main:
set ok to foo("hello") # ✗ REJECTED: type error
return 0
- Compiles to C, then to native binary via
clang -O2 - Constant folding and dead code elimination at AST level
- Release mode:
clang -O3 -flto(via--releaseflag)
| Module | Description |
|---|---|
string |
String functions, StringBuilder, formatting |
collections |
HashMap, HashSet, Stack, Queue, PriorityQueue |
fs |
File I/O, directories, path utilities |
net / http |
TCP sockets, HTTP client/server |
json |
JSON parsing and generation |
csv |
CSV parsing and generation |
datetime |
Timestamps, formatting, arithmetic |
crypto |
SHA256, MD5, SHA1, base64, UUID, random |
regex |
POSIX regex matching, find, replace, split |
sync |
Mutex, RWLock, Atomic, Barrier, Semaphore |
os |
Environment, process info, system commands |
test |
Assertions, test suites, test runner |
log |
Structured logging with levels and timestamps |
math |
Mathematical functions |
sort |
Sorting algorithms |
sql |
SQLite database bindings |
gui |
GUI via raylib |
hash |
Hashing utilities |
toml |
TOML config file parsing |
static_server |
Static file serving over HTTP |
websocket |
WebSocket protocol implementation |
select |
I/O multiplexing |
Pre-built bindings for C libraries via ep_dlopen/ep_dlsym/ep_dlcall:
raylib · sdl2 · ncurses · cairo · libpng · stb_image · miniaudio · libsndfile · curl · openssl · libsodium · zlib · sqlite · jansson · expat · pcre · libgit2 · libuv · lmdb
Note: Stdlib modules are written in ErnosPlain and call into the compiler's C runtime. They require the corresponding C runtime functions to be available.
| Tool | Command | Description |
|---|---|---|
| Compiler | ernos program.ep |
Compile to native binary |
| REPL | ernos --repl |
Interactive evaluation with session state |
| Formatter | ernos format file.ep |
Auto-format source code |
| Checker | ernos check file.ep |
Type/syntax validation without compiling |
| Test Runner | ernos test file.ep |
Run tests |
| Builtins | ernos --list-builtins |
Show all built-in functions |
| Debug | ernos file.ep --debug |
Compile with -O0 -g |
| Release | ernos file.ep --release |
Compile with -O3 -flto |
| ASAN | ernos file.ep --asan |
Compile with AddressSanitizer |
| Native | ernos file.ep --native |
Compile via native assembly (no Clang) |
| Bind | ernos bind header.h |
Generate .ep bindings from C headers |
| Transpile | ernos transpile file.py |
Translate Python/C/JS to ErnosPlain |
- macOS (ARM64 + x86_64) — primary development platform
- Linux (x86_64 + aarch64, GCC or Clang) — supported
Note: Windows has partial C runtime polyfills (
#ifdef _WIN32blocks) but is not tested or officially supported yet.
- A C compiler (
clangorgcc) - Rust (for building the bootstrap compiler)
git clone https://github.com/MettaMazza/Ernos-Programming-Language.git
cd Ernos-Programming-Language
cargo build --release# hello.ep
define main:
display "Hello from Ernos!"
return 0
./target/release/ernos hello.ep
./hello
# Output: Hello from Ernos!define add with a as Int and b as Int returning Int:
return a + b
define greet with name as Str:
display concat("Hello, " and name)
return 0
define main:
display add(10 and 20) # 30
set ok to greet("World") # Hello, World
return 0
define worker with id as Int and ch:
send id * 10 to ch
return 0
define main:
set ch to channel
spawn worker(1 and ch)
spawn worker(2 and ch)
set a to receive from ch
set b to receive from ch
display f"Total: {a + b}"
return 0
define structure User:
field name as Str
field age as Int
define greet on User:
display concat("Hi, I'm " and self.name)
return 0
define main:
set user to create User:
name is "Alice"
age is 30
set ok to user.greet()
return 0
define choice Shape:
variant Circle with radius as Int
variant Rect with width as Int and height as Int
define area with s as Shape returning Int:
check s:
if Circle with r:
return r * r * 3
if Rect with w and h:
return w * h
define main:
set c to Circle with 5
display f"Area: {area(c)}"
return 0
import "math" as m
define main:
set result to m_absolute(-42)
display result # 42
return 0
define main:
set lib to ep_dlopen("libm.dylib")
set abs_fn to ep_dlsym(lib and "abs")
set result to ep_dlcall1(abs_fn and -42)
display result # 42
set _ to ep_dlclose(lib)
return 0
# Translate existing code from other languages into ErnosPlain
ernos transpile script.py -o script.ep # Python → ErnosPlain
ernos transpile program.c -o program.ep # C → ErnosPlain
ernos transpile app.js -o app.ep # JavaScript → ErnosPlain
# Generate .ep bindings from C headers
ernos bind /usr/include/math.h -o math_bindings.epSource (.ep)
↓
Lexer → Tokens
↓
Parser → AST
↓
Type Checker (Hindley-Milner inference) — hard errors
↓
Borrow Checker (ownership analysis) — hard errors
↓
Optimizer (constant folding, dead code elimination)
↓
Codegen → C source (includes ownership safety checks)
↓
Clang -O2 → Native binary
Note: The codegen phase performs additional ownership checks (use-after-move, borrow violations) as a safety net alongside the dedicated borrow checker. Both must pass for compilation to succeed.
| File | Lines | Description |
|---|---|---|
src/lexer.rs |
~800 | Tokenizer with indentation tracking |
src/parser.rs |
~1,510 | Recursive descent parser with Pratt precedence |
src/type_check.rs |
~1,410 | Hindley-Milner type inference with unification |
src/borrow_check.rs |
~520 | Ownership, borrowing, Send/Sync analysis |
src/optimizer.rs |
~250 | AST-level constant folding and DCE |
src/codegen.rs |
~5,740 | C code generation with full runtime |
src/diagnostics.rs |
~380 | Rich error reporting with ANSI colors |
src/native_codegen.rs |
~650 | ARM64 native assembly backend (macOS + Linux) |
src/x86_64_codegen.rs |
~620 | x86_64 native assembly backend (macOS + Linux) |
src/bind_c.rs |
~1,440 | C header binding generator (zero-dependency) |
src/transpile_py.rs |
~1,880 | Python → ErnosPlain transpiler |
src/transpile_c.rs |
~1,380 | C → ErnosPlain transpiler |
src/transpile_js.rs |
~1,240 | JavaScript → ErnosPlain transpiler |
src/transpile_go.rs |
~1,360 | Go → ErnosPlain transpiler |
src/transpile_rs.rs |
~1,210 | Rust → ErnosPlain transpiler |
src/transpile_rb.rs |
~1,080 | Ruby → ErnosPlain transpiler |
src/transpile_java.rs |
~730 | Java → ErnosPlain transpiler |
src/transpile_ts.rs |
~730 | TypeScript → ErnosPlain transpiler |
src/emit_c.rs |
~570 | ErnosPlain → C emitter |
src/emit_js.rs |
~590 | ErnosPlain → JavaScript emitter |
src/emit_python.rs |
~640 | ErnosPlain → Python emitter |
Ernos compiles its own compiler. The self-hosted compiler modules:
ep_lexer.ep— Lexer (518 lines)ep_parser.ep— Parser (641 lines)ep_codegen.ep— Code generator (3,157 lines)epc.ep— Compiler driver (218 lines)- Total: 4,534 lines of ErnosPlain
# The Rust compiler compiles the self-hosted compiler
./target/release/ernos epc.ep
# The self-hosted compiler can compile programs
./epc hello.ep
./hello| Concept | Syntax |
|---|---|
| Variable | set x to 42 |
| String | "hello" or f"value: {x}" |
| Function | define foo with a and b: |
| Typed param | with a as Int and b as Str |
| Return type | define foo returning Int: |
| If/else | if cond: ... else: |
| While loop | repeat while cond: or while cond: |
| For-each | for each item in list: |
| Comparison | equals, is not equal to, <, >, <=, >=, ==, != |
| Logical | &&, ||, not, and also, or else |
| Struct | define structure Name: with field x as Type |
| Enum | define choice Name: with variant X |
| Match | check expr: with if Pattern: |
| Method | define foo on StructName: |
| Struct create | create StructName: (block with field is value) |
| Channel | set ch to channel |
| Send | send value to ch |
| Receive | set v to receive from ch |
| Spawn | spawn function(args) |
| Try | try expression |
| List literal | [1, 2, 3] or ["a", "b"] |
| Import | import "module" or import "module" as alias |
| Closure | set f to given x: return x * 2 |
| Comment | # this is a comment |
A formal specification is available in spec/ernos-spec.md, including:
- Complete EBNF grammar
- Type system rules
- Memory model (ownership, borrowing, GC)
- Concurrency model (Send/Sync)
- Standard library contracts
Conformance tests are in the conformance/ directory.
cp -R ernosplain-syntax ~/.vscode/extensions/
# Restart VS Code — all .ep files will have syntax highlightingErnos — Code that reads like English. Runs like C.