A SlopLang interpreter.
Files use the .slop extension and run with:
uv run sloperator.py path/to/program.slop— Comments start with an em dash. Statements end with sparkles.
clanker describe(count) {
vibe count > 1 {
ship “big slop”✨
} nah {
ship “small slop”✨
}
}
slop MAX = 3✨
slop count = 0✨
ralph count < MAX {
hallucinate(describe(count))✨
count = count + 1✨
}
Prints small slop twice, then big slop.
| SlopLang | Conventional | Meaning |
|---|---|---|
slop |
let |
Declare a mutable variable |
clanker |
fn |
Define a function |
vibe |
if |
Conditional |
nah |
else |
Else branch |
ralph |
while |
Loop while a condition is ✅ |
hallucinate |
print |
Print one value, then a newline |
ship |
return |
Return one value from a function |
✨ |
; |
Statement terminator (required) |
— |
// |
Start a line comment |
“ ” |
" " |
String delimiters (straight quotes are a lexical error) |
✅ |
true |
Boolean true literal |
❌ |
false |
Boolean false literal |
There are no other reserved words, and no break, continue, for, or else if.
UTF-8, case-sensitive. Identifiers match [A-Za-z_][A-Za-z0-9_]*. Spaces, tabs, and newlines are whitespace; newlines do not end statements.
Emoji tokens are ✨ (U+2728), ✅ (U+2705), and ❌ (U+274C), each optionally followed by the variation selector U+FE0F, which some keyboards emit. ✨ must follow variable declarations, assignments, ship, and expression statements. It never follows a block's closing brace. — (U+2014) starts a comment that runs to end of line.
Strings open with “ (U+201C), close with ” (U+201D), and support escapes \n, \t, \”, and \\. A string cannot contain a raw newline. Unknown escapes and unterminated strings are lexical errors.
| Type | Examples | Notes |
|---|---|---|
| Number | 0, 42, 9001 |
Arbitrary-precision integers |
| String | “hello” |
Immutable Unicode text |
| Boolean | ✅, ❌ |
Required by conditions |
| Nil | Result of a function with no ship |
No source literal |
| Function | hallucinate, describe |
Built-in or user-defined |
No implicit conversions.
slop declares a mutable variable and requires an initializer. A scope cannot declare a name twice, but an inner block may shadow an outer name.
slop score = 10✨
slop LIMIT = 100✨
score = score + 5✨
score = score + 1✨
Assignment is a statement, not an expression: name = expression✨. It updates the nearest existing slop variable. Reading or assigning an undefined name is a runtime error.
Every brace block is a lexical scope. Assignment searches the current scope, then each enclosing scope.
Conditions take no parentheses and must be booleans; there is no truthiness.
vibe score >= 10 {
hallucinate(“ship it”)✨
} nah {
hallucinate(“keep working”)✨
}
ralph score > 0 {
score = score - 1✨
}
nah must be followed by a block; nest a vibe for another condition. ralph checks its condition before each iteration.
A tree-walking interpreter for SlopLang, written in Python.
uv run sloperator.py examples/fib.slop| Path | What it is |
|---|---|
sloperator.py |
Command-line entrypoint |
sloperator/lexer/ |
Source text to tokens |
sloperator/parser/ |
Tokens to AST (ast.py holds the node definitions) |
sloperator/evaluator/ |
Walks the AST: values, environments, the interpreter |
sloperator/runner.py |
Runs source through all three stages |
docs/spec.md |
The language specification |
examples/ |
Example programs |
tests/ |
Pytest suite |
playground/ |
A tiny web server and editor page for running programs |
uv run pytest # tests
uv run ruff format --check # formatting
uv run ruff check # linting
uv run ty check # type checkinguv run playground/server.pyThen open http://localhost:8080.