{
"path": "/projects/numlang",
"site": "at://did:plc:ofrbh253gwicbkc5nktqepol/site.standard.publication/3mfyq5mpohw25",
"tags": [
"c",
"compiler",
"python"
],
"$type": "site.standard.document",
"title": "Numlang",
"description": "An esoteric stack-based language that compiles to C via a Python compiler, using only numbers and punctuation.",
"publishedAt": "2026-04-06T00:00:00.000Z",
"textContent": "Numlang is an esoteric stack-based language that compiles to C through a Python compiler. The character set is 0-9 ^ & + - / . | ; % ~ \" ! — no letters, no keywords.\n\nData model\n\nAll values are 64-bit IEEE 754 doubles. The runtime has a stack (depth 1000) and 100 named variables vars[0]–vars[99], all initialised to 0.\n\nInstallation\n\nThis installs the numlangc command.\n\nUsage\n\nLanguage reference\n\nComments\n\ntext — ignored to end of line.\n\nPushing values\n\n| Syntax | Effect |\n|--------|--------|\n| N (integer literal) | Push integer N, unless N is a special opcode (see tables below) |\n| N.M (float literal) | Push float N.M — never treated as an opcode |\n| |n or |nn | Push value of variable n (0–99) |\n\n> Tip: Use float syntax (10.0 instead of 10) to push numbers that match opcode aliases.\n\nStack manipulation\n\n| Code | Name | Effect |\n|------|------|--------|\n| 16 | DUP | Duplicate top of stack |\n| 17 | SWAP | Swap top two elements |\n| 18 | DROP | Discard top of stack |\n\nArithmetic\n\n| Symbol | Effect |\n|--------|--------|\n| + | pop b, pop a → push a + b |\n| - | pop b, pop a → push a − b |\n| ` | pop b, pop a → push a × b |\n| / | pop b, pop a → push a ÷ b |\n| % | pop b, pop a → push fmod(a, b) |\n\nComparison (push 1.0 = true, 0.0 = false)\n\n| Code | Meaning |\n|------|---------|\n| 10 | a < b |\n| 11 | a > b |\n| 12 | a == b |\n| 13 | a != b |\n| 14 | a <= b |\n| 15 | a >= b |\n\nControl flow\n\n| Syntax | Effect |\n|--------|--------|\n| 20 | IF — pops condition; executes body if non-zero |\n| 28 | ELSE — separates if/else bodies |\n| 30 … ; | WHILE — pops condition each iteration |\n| 50 … ; | REPEAT — executes body N times (pushes 0-based index each iteration) |\n\nVariables\n\nI/O\n\n| Symbol | Effect |\n|--------|--------|\n| | | Pop and print as number (with newline) |\n| ~ | Pop and print as ASCII character |\n| ^ | Read double from stdin and push |\n| \"...\" | Print string literal |\n\nFunctions\n\nFunctions may be defined in any order. Forward calls and recursion are supported.\n\nGotchas\n\n1. Opcode collisions: Integer literals matching opcode numbers are interpreted as opcodes. Use float syntax (e.g., 42.0).\n2. Division vs functions: /` followed by an integer defines a function. Use float divisors to avoid this.\n\nExamples\n\nHello, World!\n\nVariables\n\nWHILE countdown\n\nFunctions\n\nProject layout\n\nLicence\n\nAGPL 3.0",
"canonicalUrl": "https://docs.ewancroft.uk/projects/numlang"
}