A modern, Python-inspired programming language with a complete toolchain: interpreter, bytecode VM, REPL, linter, formatter, optimizer, debugger, and LSP server.
📦 Install • 🚀 Quick Start • 📖 Language • 📚 Standard Library • 🔧 Toolchain • 📄 Docs • 🗺️ Roadmap
Status: Actively developed. Core language is feature-complete with 2 501 passing tests. Standard library is growing (80+ pure EL modules with 50+ test files). APIs may evolve before 1.0.
EL is an indentation-based, dynamically-typed language with clean Python-inspired syntax. It is designed to be readable, predictable, and equipped with real tooling from day one.
# Functions with defaults and type annotations (unenforced, informational)
def greet(name: str, excited: bool = false) -> str:
suffix = "!" if excited else "."
return f"Hello, {name}{suffix}"
# Classes with inheritance
class Animal:
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
return f"{self.name} makes a sound."
class Dog(Animal):
def speak(self) -> str:
return f"{self.name} barks!"
# Pattern matching
def describe(value):
match value:
case 0:
return "zero"
case [x, *rest]:
return f"list starting with {x}"
case {"key": v}:
return f"dict with key={v}"
case _:
return "something else"
# Async/await
async def fetch_all(urls: list) -> list:
results = await gather(*[fetch(u) for u in urls])
return results
# Generators
def fibonacci():
a, b = 0, 1
while true:
yield a
a, b = b, a + b
# Bitwise operations and numeric literals
mask = 0xFF & (value >> 4)
flags = 0b1010 | 0b0101
big = 1_000_000| Category | Features |
|---|---|
| Syntax | Indentation blocks, f-strings with format specs, walrus :=, extended unpacking [first, *rest, last] |
| Functions | Defaults evaluated at call time, *args/**kwargs, call-site */** unpacking, positional-only params (PEP 570) |
| Classes | Single inheritance, implicit self, __init__, super(), @property / @staticmethod / @classmethod, dunder dispatch |
| Control flow | if/elif/else, while, for-in, match/case (literals, tuples, dicts, OR-patterns, class patterns, guards) |
| Exceptions | try/except[/else][/finally], typed catches, raise/re-raise, dotted exception types, Python exception compatibility |
| Async | async def, await, async for, async with, async generators, gather() builtin |
| Generators | yield, generator expressions, lazy evaluation |
| Imports | Dotted and relative imports, packages with __init__.el, star-import, configurable EL_PATH / -I |
| Operators | Full bitwise suite (&, |, ^, ~, <<, >>), augmented assignments (&=, |=, ^=, <<=, >>=) |
| Literals | Binary 0b, octal 0o, hex 0x, underscore separators 1_000_000 |
| Builtins | ord, chr, len, range, enumerate, zip, map, filter, sorted, reversed, repr, type, isinstance, callable, getattr/setattr, py_import, and more |
| FFI | py_import(), py_type(), py_isinstance(), py_dir() — full Python library access from EL |
pip install -e .Requires Python 3.9+. Installs the el command and trace utilities.
# Interactive REPL (multi-line editing, history, tab completion)
el
# Run a file
el run examples/hello.el
# Lint a directory
el lint src/
# Format files in-place
el fmt --write src/
# Show version
el --versionel> :help — list commands
el> :vars — show all variables
el> :functions — show all functions
el> :history — show input history
el> :clear — clear the screen
el> :exit — quit
Set EL_BASIC_REPL=1 to use the plain REPL without prompt_toolkit features.
EL ships two layers of stdlib:
Thin wrappers over Python's standard library for rapid development:
| Module | Coverage |
|---|---|
fs |
25+ file operations (read, write, glob, walk, basename, …) |
http |
Full HTTP client with sessions |
datetime |
38 date/time functions with timezone support |
regex |
19+ regex functions (match, search, sub, compile, flags) |
math |
Extended mathematical operations |
json |
JSON encode/decode |
asyncio, time, os, sys, collections, functools, random |
Core utilities |
80+ modules written entirely in EL — no Python dependency at runtime. Enabled by default (EL_PURE_STDLIB=1):
regex (NFA matching, flags), heap/deque/counter (data structures), csv/text_extra, pure_json/yaml/toml (data formats), tree/graph/bloom_filter (advanced structures), sorting/searching (algorithms), pure_itertools/functools (functional), statistics/math (numerics), fs (filesystem), datetime/text/collections_extra, struct/encoding/compression/crypto/msgpack/url
pathlib (Path class with / joining, @property, exists, read/write text), io (StringIO stream I/O), contextlib (nullcontext, suppress, ExitStack), html (HTML5 templating), xml (XML generation/parsing), markdown (MD-to-HTML converter), pretty (pretty-printing), validate (email, URL, IP, hex-color validation), template ({{ key }} substitution engine), textwrap (wrap/fill/shorten/dedent)
bencode (BitTorrent encoding), base62 (short IDs), hashes (DJB2, FNV-1a, CRC-8), uuid (UUID v4 generation), mime (MIME type detection), url (parse, quote, unquote, join), diff (LCS, similarity, ndiff, unified diff), ini_parser (INI config parse/stringify), dotenv (.env parsing), slugify (URL-safe slugs), semver (semantic versioning), version (version compare/sort), crontab (cron expression matching)
pipe (pipe/compose/curry/tap), queue (Queue, Stack, PriorityQueue), observer (pub-sub), lazy (lazy evaluation), option/result (monads), statemachine (FSM), perm (bitfield permissions), retry (retry with backoff), cache (LRU cache), cli (status_ok/fail/ask/menu), cmd (color, table, progress), ansi/console (terminal control), stopwatch (performance timer)
svg (SVG image generation), irc (IRC message parsing/building), humanize (intcomma, filesize, ordinal, naturalday), json_tool (merge, flatten, search), progress (progress bar, ETA, bytes_bar), system (hostname, username, pid), compat (version info)
See docs/pure-stdlib-complete-summary.md for the full function reference.
el lint src/ # lint a directory
el lint --summary src/ # summary view
el lint --format=json src/ # machine-readable output
el lint --list-rules # list all rules with descriptions
el lint --format=json --explain=L3009 # explain a specific ruleRule categories: undefined/unused names, shadowing, constant conditions, unreachable code, inconsistent returns, duplicate match literals, call-site errors (positional-after-keyword, duplicate kwargs, signature mismatches), style (dead stores, redundant comparisons, unnecessary else, literal-only expressions).
Auto-fixes are available for common issues:
el lint --fix src/ # apply safe auto-fixes
el lint --fix --fix-rule=L3001 src/ # apply one specific fixSuppressions:
x = 1 # ellint: disable=L3002
# ellint: disable-next=L3001,L3002
# ellint: file-disable=L3001el fmt src/ # show diff only
el fmt --write src/ # apply in-placeConservative constant folding and algebraic simplifications, guarded by size limits. Configurable via el.toml.
el run --opt program.elBoth the interpreter and VM support breakpoints, step/next/continue, conditional breakpoints, watches, and JSON event output for tooling integration.
# Interpreter debugger
el run --debug --break examples/hello.el:10 examples/hello.el
el run --debug --debug-commands "b :10?i>3; p i; c" examples/loop.el
# VM debugger (text and JSON modes)
el run --engine vm --debug --break :2 --debug-commands "n; bl; c" examples/loop.el
el run --engine vm --debug --break :2 --debug-json --debug-commands "c" examples/loop.elSee docs/debugger.md and docs/debugger-json.md for full reference.
An experimental stack-based VM with IR compilation. Covers a growing subset of EL; the interpreter remains the default and most complete runtime.
el run --engine vm examples/arith.el
el run --engine vm --disasm examples/arith.el # show IR before running
el run --engine vm --trace --trace-json examples/arith.el
el run --engine vm --profile-vm examples/arith.elpython -m el.lsp_server # communicates over stdioCapabilities: diagnostics, code actions (quick fixes), go-to-definition (including cross-file), find references (scope-aware, cross-file), document/workspace symbols, call hierarchy, rename (scope-aware, cross-file), smart completions with ranking, signature help, code folding, semantic tokens (23 types, 10 modifiers), hover info, background workspace indexing (up to 1 000 files), persistent disk cache with gzip compression.
Set EL_LSP_DEBUG=1 for server logs to stderr. Use EL_LSP_SQLITE_CACHE=1 for the SQLite index backend (4× faster updates).
el-trace-grep # grep trace events
el-trace-cat # pretty-print a trace file
el-trace-tail # stream a live trace
el-trace-stats # aggregate statisticsSee docs/trace.md for full reference including rotation, gzip, time filters, and predicates.
el cache --cache-status src/ # show cache size and location
el cache --cache-prune src/ # remove stale entries
el cache --cache-dry-run src/ # preview what would be deleted[lint]
disable_next_mode = "code" # "code" (default) or "physical"
[optimizer]
constant_folding = true
max_inline_size = 20CLI flags, environment variables, and el.toml are merged in precedence order: env > CLI > config file. Use el --print-config-effective to see the resolved values.
| Document | Contents |
|---|---|
docs/README.md |
User guide and tutorials |
docs/language.md |
Complete language specification |
docs/api/builtins-api.md |
Built-in functions reference |
docs/api/interpreter-api.md |
Interpreter API |
docs/pure-stdlib-complete-summary.md |
All 204 pure EL functions |
docs/debugger.md |
Debugger command reference |
docs/debugger-json.md |
Debugger JSON event schema |
docs/trace.md |
Trace tooling and predicates |
docs/rules.md |
Linter rule reference |
docs/schemas/ |
JSON schemas for all CLI outputs |
docs/rfcs/ |
Design RFCs |
# Set up a virtual environment
python -m venv .venv && source .venv/bin/activate # Linux/macOS
# or: .\.venv\Scripts\Activate.ps1 # PowerShell
# Install in editable mode with test deps
pip install -e .
pip install pytest jsonschema pytest-asyncio
# Run the full test suite
python -m pytest tests/ -qCI runs on Python 3.9–3.13 via GitHub Actions (see .github/workflows/ci.yml).
| Milestone | Status |
|---|---|
| Core interpreter | ✅ Complete |
| Bytecode VM (subset) | 🔄 In progress |
| Linter + formatter | ✅ Complete |
| LSP server | ✅ Complete |
| Debugger (interpreter + VM) | ✅ Complete |
| Pure EL stdlib (80+ modules) | ✅ Complete |
bytes / bytearray type |
✅ Complete |
del statement |
✅ Complete |
global / nonlocal |
✅ Complete |
| Multiple inheritance + dunder dispatch | ✅ Complete |
Exception groups / raise from |
✅ Complete |
open() / file I/O |
✅ Complete |
format() / f-string format specs |
✅ Complete |
Reflection builtins (hasattr, getattr, setattr, delattr) |
✅ Complete |
iter() / next() iterator protocol |
✅ Complete |
| Pure EL argparse module | ✅ Complete |
| Pure EL logging module | ✅ Complete |
| Pure EL unittest module | ✅ Complete |
| Type annotations (parse + lint) | 📋 Planned |
VM: try/except, classes, with |
📋 Planned |
| Self-hosting (EL written in EL) | 🔭 Long-term |
Pure EL pathlib, datetime OOP, io, html, xml, markdown |
✅ Complete |
Pure EL contextlib, cache (LRU), semver, ini_parser |
✅ Complete |
Pure EL uuid, humanize, diff, pretty, validate |
✅ Complete |
Pure EL bencode, base62, cmd, hashes, mime, dotenv |
✅ Complete |
Pure EL pipe, queue, observer, statemachine, textwrap, svg |
✅ Complete |
Pure EL lazy, option, result monads |
✅ Complete |
Pure EL perm (bitfield), irc (messaging), slugify, dedup |
✅ Complete |
Pure EL ansi / terminal control |
✅ Complete |
MIT