Mini APL in Python Language Experiment. A first-generation APL interpreter with the rank operator, namespaces, and Python FFI. Uses APL arrays (shape + flat data) as the internal data model. Inspired by Rodrigo Girão Serrão's RGSPL and Iverson's Dictionary of APL.
More extensive documentation is available here
MARPLE runs on the Raspberry Pi Pico 2 via MicroPython. On the Pimoroni Presto, the REPL session mirrors to the 480x480 touchscreen LCD with a custom APL bitmap font. See the demo videos — primitives, dfns, the rank operator, namespaces, and file I/O, all running on the Pico.
- 40+ primitive functions — arithmetic, comparison, boolean, structural, circular/trig, match/tally, membership
- Operators — reduce (
/), scan (\), inner product (f.g), outer product (∘.f), rank (⍤) - Rank operator —
(f⍤k)applies any function along any axis:(⌽⍤1) Mreverses rows,(+/⍤1) Msums rows - From function (
⌷) — leading-axis selection that composes with rank - Direct functions (dfns) —
{⍵}syntax with guards, recursion via∇, default⍺ - Direct operators (dops) —
{⍺⍺ ⍵}adverbs and{⍺⍺ ⍵⍵ ⍵}conjunctions with function or array operands - Iverson stack-based parser — correct operator binding precedence following the Dictionary of APL
- Namespaces —
$::str::upper 'hello',#importdirectives,::separator - I-beam operator (
⌶) — Python FFI for extending MARPLE with Python code - Error handling —
⎕EA(execute alternate),⎕EN(error number),⎕DM(diagnostic message),⎕SIGNAL - Format function (
⎕FMT) — Dyalog-compatible formatting with I/F/E/A/G codes, text insertion, G pattern, character matrices - System variables —
⎕IO,⎕CT,⎕PP,⎕RL,⎕A,⎕D,⎕TS,⎕WSID,⎕UCS,⎕NC,⎕EX,⎕FR - Data representation —
⎕DRqueries/converts internal types;⎕FR←1287enables exact decimal arithmetic - Numeric type system — automatic upcast/downcast prevents integer overflow; boolean uint8 for comparisons
- Matrices — reshape, transpose, bracket indexing (
M[r;c]any rank, index shape preserved), matrix inverse (⌹) - Numpy backend — automatic vectorization (73x faster for element-wise, 380x for outer product), with pure-Python fallback
- PRIDE web IDE — browser-based IDE over WebSocket with language bar, workspace panel, click-to-re-edit, session save/load as markdown, session history, multi-line input
- Pico web bridge — evaluate APL on a connected Pico from the browser (
--pico-port /dev/ttyACM0) - Presto LCD mirror — REPL session mirrors to the Pimoroni Presto's 480x480 touchscreen with APL bitmap font
- Terminal REPL — live backtick→glyph input, workspace save/load, APL-style formatting
- Script runner —
marple script.marplewith session transcript output - 612 tests (560+ interpreter + 50 web), dispatch-dict architecture, pyright strict
Install uv if you don't have it, then:
uv venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
uv pip install marple-lang
marpleMARPLE v0.3.0 - Mini APL in Python
CLEAR WS
⍳5
1 2 3 4 5
+/⍳100
5050
fact←{⍵≤1:1⋄⍵×∇ ⍵-1}
fact 10
3628800
double←{⍵+⍵}
double ⍳5
2 4 6 8 10
M←3 4⍴⍳12
(⌽⍤1) M
4 3 2 1
8 7 6 5
12 11 10 9
$::str::upper 'hello'
HELLO
python -m marple.web.serverOpen http://localhost:8888/ in your browser. PRIDE (the MARPLE web IDE) communicates over WebSocket. Features:
- Clickable language bar for APL glyph input
- Click any previous input line to re-edit and re-submit
- Session save/load as markdown (Session menu)
- Workspace panel showing variables and functions
- Session history (up/down arrows), multi-line input (Shift+Enter)
- Link to MARPLE documentation
To evaluate APL on a connected Raspberry Pi Pico 2 from the browser:
python -m marple.web.server --pico-port /dev/ttyACM0A Local/Pico toggle appears in the header bar. Switch to Pico mode to send expressions to the Pico over USB serial.
marple examples/01_primitives.marple # run and display
marple examples/01_primitives.marple > out.txt # capture session transcriptNine demo scripts are included in examples/:
01_primitives.marple— arithmetic, vectors, matrices, reduce, products02_dfns.marple— user functions, guards, recursion, rank operator03_namespaces.marple— system library, imports, file I/O, i-beams04_errors.marple— ea/en error handling, error codes05_pico_io.marple— file I/O on Raspberry Pi Pico 206_numeric_types.marple— ⎕DR, ⎕FR, boolean dtype, overflow protection, decimal arithmetic07_cr_fx.marple— ⎕CR, ⎕FX, ⎕NC, dynamic function definition08_operators.marple— operators, dops, reduce/scan with dfns, replicate09_fmt.marple— ⎕FMT formatting with I/F/E/A/G codes, text insertion, patterns
If you have a Dyalog APL keyboard layout installed (e.g. via setxkbmap with grp:win_switch), you can use the Win key to type APL glyphs directly.
Alternatively, type APL glyphs using backtick prefixes — they appear immediately as you type:
| Key | Glyph | Key | Glyph | Key | Glyph | Key | Glyph |
|---|---|---|---|---|---|---|---|
`r |
⍴ | `i |
⍳ | `l |
← | `w |
⍵ |
`a |
⍺ | `V |
∇ | `x |
⋄ | `c |
⍝ |
`- |
× | `= |
÷ | `< |
≤ | `> |
≥ |
`/ |
≠ | `o |
○ | `* |
⍟ | `2 |
¯ |
`q |
⌽ | `Q |
⍉ | `g |
⍋ | `G |
⍒ |
`t |
↑ | `y |
↓ | `n |
⊤ | `N |
⊥ |
`J |
⍤ | `I |
⌷ | `j |
∘ | `D |
⌹ |
`B |
⌶ |
| Command | Action |
|---|---|
)off |
Exit |
)clear |
Clear workspace |
)wsid [name] |
Show or set workspace ID |
)save [name] |
Save workspace (sets WSID if name given) |
)load name |
Load workspace |
)lib |
List saved workspaces |
)fns [ns] |
List defined functions (optionally in namespace) |
)vars |
List defined variables |
pip install -e .[test]
pytest
pyright src/To run without numpy (pure-Python mode):
MARPLE_BACKEND=none pytest| Module | Purpose |
|---|---|
arraymodel.py |
APLArray(shape, data) — the core data structure |
backend.py |
Numpy/CuPy/ulab detection with pure-Python fallback |
tokenizer.py |
Lexer for APL glyphs, numbers, strings, qualified names |
parser.py |
Iverson stack-based parser with operator binding precedence |
interpreter.py |
Dispatch-dict evaluator with dfn environments |
functions.py |
Scalar functions with pervasion (numpy-accelerated) |
structural.py |
Shape-manipulating and indexing functions |
cells.py |
Cell decomposition and reassembly for the rank operator |
namespace.py |
Hierarchical namespace resolution and system workspace |
errors.py |
APL error classes with numeric codes |
repl.py |
Interactive read-eval-print loop |
script.py |
Script runner with session transcript output |
terminal.py |
Raw terminal input with live glyph translation |
glyphs.py |
Backtick → APL character mapping |
workspace.py |
Directory-based workspace persistence |
stdlib/ |
Standard library: string, I/O, and error handling |
- RGSPL — Rodrigo Girão Serrão's Python APL interpreter (design reference)
- RGSPL blog series — step-by-step interpreter build
- Iverson's Dictionary of APL — the rank operator and leading-axis theory
- Language spec — full first-generation APL reference and roadmap
- Rank operator spec — detailed rank operator design
- Indexing spec — From function and indexing approach
- Namespaces spec — namespaces, i-beams, and standard library