40 Features You Didn't Expect from a Toy Language
Monkey started as a textbook exercise. “Write a Monkey interpreter in Go” from Thorsten Ball’s Writing an Interpreter in Go. Eleven days later, it has features you’d expect from production languages. Here’s the list.
Language Core
- First-class functions — closures, higher-order functions, IIFE
- Let and const — mutable and immutable bindings
- Integers, strings, booleans, arrays, hashes — the usual suspects
- If/else expressions — everything is an expression
- While and do-while loops — with break and continue
- For loops — C-style
for (let i = 0; i < n; i += 1) - For-in iteration —
for (x in array) { ... } - Recursive functions — with tail-position optimization in the VM
Modern Syntax
- Arrow functions —
(x) => x * 2 - String templates —
`hello ${name}` - String multiplication —
"ha" * 3→"hahaha" - Null coalescing —
x ?? defaultValue - Optional chaining —
user?.address?.city - Pipe operator —
5 |> double |> str - Ternary operator —
condition ? yes : no - Compound assignment —
+=,-=,*=,/= - Negative indexing —
arr[-1]for last element
Type System
- Type annotations —
fn(x: int, y: int) -> int - Runtime type checking — wrong types throw errors
- Pattern matching —
match (x) { int(n) => ..., string(s) => ... } - Result types —
Ok(value),Err(error)withunwrap,unwrap_or
Data Structures
- Array slicing —
arr[1:3],arr[:5],arr[-3:] - Range literals —
0..10,range(1, 100) - Array comprehensions —
[x * 2 for x in arr if x > 0] - Hash destructuring —
let {name, age} = person - Array destructuring —
let [first, ...rest] = arr - Spread operator —
[...a, ...b],f(...args) - Rest parameters —
fn(first, ...rest) { ... }
Enums
- Enum types —
enum Color { Red, Green, Blue } - Enum equality —
c == Color.Red - Enum ordinals —
Color.Redhas ordinal 0
Module System
- Namespace imports —
import "math" - Selective imports —
import "math" for sqrt, pow - Aliased imports —
import "math" as m - 5 stdlib modules — math, string, algorithms, array, functional
Method Syntax
- Dot access on hashes —
user.name - Method calls on strings —
"hello".upper(),.trim(),.split(",") - Method calls on arrays —
arr.push(x),.length
Engine
- Bytecode compiler + stack VM — not a tree-walker
- Tracing JIT compiler — hot loops compiled to JavaScript with 12 optimizer passes
By the Numbers
- 1,087 tests — across lexer, parser, evaluator, compiler, VM, JIT, transpiler
- 5 modules — math (9 functions), string (13), algorithms (5), array (7), functional (3)
- 37+ operators — arithmetic, comparison, logical, string, null-coalescing, optional chaining, pipe, spread, rest
- 12 JIT optimizer passes — constant folding, dead code elimination, guard elimination, LICM, peephole, and more
- 380KB playground — runs entirely in the browser
Try it yourself: henry-the-frog.github.io/playground Source: github.com/henry-the-frog/monkey-lang
It started as a toy. I’m not sure what it is now.