Parrot
Parrot is the register-based virtual machine that grew out of the Perl 6 project: born in August 2001 from an April Fools' joke about Perl and Python merging, designed by Dan Sugalski to run every dynamic language on one runtime, and the platform Rakudo Perl 6 ran on for its first seven years. Its more than a hundred monthly releases from 2006 to 2016, its Parrot Design Documents, and its compiler toolkit (PGE, PCT and NQP) shaped Perl 6 far more than its bytecode ever did; MoarVM replaced it as Rakudo's runtime in 2015, the last supported release was 8.1.0 in February 2016, and the project posted an inactivity notice in August 2021 - though its last release manager was still committing fixes in December 2025
Created by Dan Sugalski - designer and 'architect' of Parrot from its start in 2001 until he passed the role to Chip Salzenberg on 21 March 2005; Simon Cozens made the first check-in on 29 August 2001, named the project after his own April Fools' prank and managed releases 0.0.1-0.0.4; Leopold Tötsch was 'patchmonster' and release manager from 0.0.13 (October 2003) to 0.4.5 (June 2006); Allison Randal was architect from 0.4.6 (August 2006) to 2.8.0 (September 2010) and chaired the Parrot Foundation; Christoph Otto was architect from 2.9 (October 2010) until about 5.0 (January 2013); Reini Urban and Bruce 'Util' Gray alternated as release managers from 2013 to 2016
Parrot was the virtual machine the Perl community built for Perl 6 - and, more ambitiously, for every dynamic language. Conceived by Dan Sugalski in 2000-2001 as a register machine rather than the stack machines of Java, .NET and Perl 5, it promised that Perl, Python, Ruby and Tcl could compile to one bytecode, share one garbage collector and one object model, and call each other’s libraries. For a decade it was the beating heart of Perl 6: Rakudo was written inside its repository, its grammar engine parsed Perl 6 rules, and its “Not Quite Perl” compiler language became the language Rakudo is still written in. But the ambition was larger than the volunteer workforce, Perl 6 itself took fifteen years to reach a stable release, and in 2013 one of Rakudo’s developers wrote MoarVM as a leaner replacement. Rakudo suspended Parrot support in February 2015, the last Parrot release was 8.1.0 in February 2016, and the project posted an inactivity notice in August 2021. Parrot’s story is an unusually well-documented case study in language-runtime engineering: its Parrot Design Documents, monthly release cadence and public post-mortems are still read by people building virtual machines.
History and Origins
An April Fools’ joke, and a real Perl 6 engine
On 1 April 2001 Simon Cozens published “Programming Parrot” on perl.com: a fake interview in which Larry Wall and Guido van Rossum announced that Perl and Python would merge into a single language called Parrot. Guido was reportedly quoted as wanting a name that began with “P” and sounded right in /usr/bin/, with the Monty Python dead-parrot sketch supplying it, and O’Reilly produced a mock cover for a Programming Parrot book. The prank landed at a moment when the joke had a kernel of truth. Larry Wall had announced Perl 6 in July 2000 as a from-scratch rewrite, and Dan Sugalski, who had taken charge of the interpreter design, was already planning an engine that would not be tied to Perl. When the real project needed a name, it took the joke’s, and Cozens - “as penance”, as the Parrot FAQ later put it - became its first release manager.
The code began on 29 August 2001, when Ask Bjørn Hansen set up the CVS repository and Cozens checked in his working directory with the note “Dan, feel free to nuke.” Parrot 0.0.1 shipped on 10 September 2001. Cozens’ perl.com article “Parrot: Some Assembly Required” (18 September 2001) described the state of play: a register machine with 32 registers each of integer, floating-point, string and PMC type; a Parrot assembler and disassembler; more than a hundred commits in the first week; and Gregor Purdy’s tiny Jako language already compiling to Parrot bytecode. PMCs - “Parrot Magic Cookies”, later renamed Polymorphic Containers - were described as “almost like Perl 5’s SVs, only more so”: tagged values whose behaviour is defined entirely by a vtable of function pointers, so that a Python integer and a Perl integer could live side by side and each behave as its language expected.
The Sugalski years (2001-2005)
Sugalski’s design was worked out in public in Parrot Design Documents (PDDs) and on his blog Squawks of the Parrot. The register-machine choice was defended on pragmatic grounds - the Parrot FAQ argued that “we’re already running with a faster opcode dispatch than any of them are, and having registers just decreases the amount of stack thrash we get”, pointing to Apple’s 68K emulator as a register-based VM that worked - and on the grounds that decades of hardware-compiler literature on register allocation could be reused. Continuations were first-class from the start, subroutine calls were built on them, and the calling conventions (PDD 03) were designed to let any language’s calling semantics be expressed.
Early releases were managed by Cozens (0.0.1-0.0.4), Jeff Goff (0.0.5-0.0.8, the first with release names such as “Octarine”), and Steve Fink (0.0.9 “Nazgul” to 0.0.11 “Dubloon”). Sean O’Rourke’s prototype Perl 6 compiler and Goff’s Python and Ruby experiments joined the languages/ tree in 2002, along with Melvin Smith’s IMCC, the “intermediate code compiler” whose input language became PIR. Leopold Tötsch took over as release manager and “patchmonster” with 0.0.13 “Screaming Pumpkin” on 31 October 2003 and held the job until mid-2006. O’Reilly’s Perl 6 Essentials (2003) and Perl 6 and Parrot Essentials (2004), by Allison Randal, Sugalski and Tötsch, gave the VM its first book-length treatment.
The most public episode of this period was the “Pie-thon”. At OSCON 2003 Sugalski bet Guido van Rossum that Parrot would run a pure-Python benchmark faster than CPython by the following year’s conference; his blog of 14 July 2003 set the stakes at “$10, a round of drinks, and a pie at 10 paces” and specified the rules (Python 2.3 bytecode, at least 30 seconds of runtime, best of three on the same x86 Linux box). Parrot 0.1.0 “Leaping Kakapo” appeared on 29 February 2004, but by OSCON in August the bytecode translator ran only four of the seven benchmarks. Sugalski conceded at the Python lightning talks; Guido graciously declined to throw the pie, and - by Sugalski’s own account in “Pies away anyway” (1 August 2004) - he was pied instead at The Perl Foundation’s auction that evening.
In March 2005 Sugalski posted “Passing on the hat” to the perl6-internals list: “it’s been four and a half years … and I’ll admit, I’m just tired.” He handed the architect’s role to Chip Salzenberg, the former perl 5.004 pumpking, and by the autumn had left the project altogether. His “Parrot post-mortem” of 20 October 2005 - a candid list of what went right (“trusting the code gnomes”) and what went wrong - remains one of the most-quoted retrospectives on open-source VM design.
Funding, foundations and monthly releases (2005-2010)
The same spring the Dutch NLnet Foundation began funding Parrot through The Perl Foundation, reportedly with Tötsch as the principal paid developer; release 0.2.0 of 8 May 2005 was named “NLnet” in thanks. NLnet’s own review two years later found “a marked increase in the pace of development in early 2005”, and from 0.2.x onwards Parrot shipped roughly every month - by 2007 on a fixed monthly schedule (nominally the third Tuesday), with the release-manager hat rotating among Jerry Gay, Patrick Michaud, Will Coleda, Matt Diephouse, chromatic, Jonathan Worthington, Bob Rogers, Bernhard Schmalhofer and others. Allison Randal became architect with 0.4.6 in August 2006 and, on 18 June 2007, moved the project from Perl’s GPL/Artistic dual licence to the Artistic License 2.0.
The tooling that made Parrot matter to Perl 6 was built in these years. Patrick Michaud’s Parrot Grammar Engine (PGE, 2004) implemented Perl 6 rules and a hybrid recursive-descent/operator-precedence parser, and Jeff Horwitz’s mod_parrot (introduced on perl.com in December 2004) embedded the VM in the Apache web server. In June 2007 he created the Parrot Compiler Toolkit (PCT), a set of PIR classes for grammars, abstract syntax trees (PAST) and opcode trees (POST), and moved NQP - “Not Quite Perl”, a Perl 6 subset small enough to bootstrap - into the core in November. With PCT a language implementer wrote a PGE grammar and NQP action methods and got a compiler; the languages/ tree grew to roughly three dozen directories by mid-2007 (APL, BASIC, Befunge, C99, .NET bytecode, ECMAScript, Forth, Lisp, Lua, Scheme, Tcl, WMLScript, Z-code and more), and the Perl 6 compiler inside it was named Rakudo in early 2008.
In June 2008 the Parrot Foundation was announced as a Washington State non-profit to hold the project’s copyrights and trademarks, chaired by Randal with chromatic as secretary; parrot.org, a Trac instance and Subversion replaced the Perl-hosted infrastructure. Rakudo left the repository in February 2009, and on 17 March 2009 Randal released Parrot 1.0.0 “Haru Tatsu”: the first “supported” release, with a frozen public API, a formal deprecation policy, a supported release every three months, and all remaining languages sent to their own repositories. Rakudo Star, the first “usable, early adopter” Perl 6 distribution, followed on 29 July 2010, with Parrot as its runtime.
Design Philosophy
Parrot’s design rested on a handful of convictions, most of them set out in the PDDs:
- Registers, not stacks. Opcodes name registers directly (
add $I0, $I1, $I2), avoiding push/pop traffic and letting IMCC do conventional register allocation. Each subroutine frame has as many registers of each kind as it needs, allocated in the call context rather than a fixed global set (the original fixed set of 32 per type was later replaced by per-frame allocation). - Four kinds of value. Integers (
I), floats (N) and strings (S) are native and fast; everything with language-specific semantics is a PMC (P). Strings carry an encoding and charset rather than being byte buffers, with ICU providing Unicode tables. - Semantics live in the PMC vtable. Addition, stringification, method lookup, invocation, iteration and comparison are vtable slots. A hosted language ships its own PMC types (a Perl scalar, a Python list, a Tcl string) and the same opcode does the right thing for each, so cross-language calls need no marshalling.
- Continuations underneath everything. Subroutine return, exception handling and coroutines were all expressed as continuations; closures and lexical pads (PDD 20) were built in rather than emulated.
- Language interoperability as the goal. PDD 31 defined how each high-level language (HLL) gets its own namespace and type mappings, so that a Ruby program could load a Perl 6 module.
- A compiler toolkit, not just a bytecode. PGE, PCT and NQP were meant to make writing a language for Parrot a weekend project, and the Squaak tutorial walked newcomers through one.
- Design in public. PDD 00 defined the PDD process itself; the numbered documents - calling conventions (03), coding standards (07), garbage collection (09), embedding (10), objects (15), PMCs (17), security (18), PIR (19), lexicals (20), namespaces (21), I/O (22), exceptions (23), events (24), concurrency (25), AST (26), multiple dispatch (27), strings (28), installation (30) and HLL interoperation (31) - were the project’s constitution.
Key Features
PASM, PIR and bytecode
Parrot code exists at three levels. PASM (Parrot assembly) is a one-to-one textual form of the opcodes. PIR (Parrot Intermediate Representation), accepted by IMCC, adds subroutine declarations with parameters and return values, infix syntax that expands to opcodes, symbolic ($I0-style) temporaries with automatic register allocation, and directives for lexicals, namespaces and classes; it was the target of every serious compiler. Both compile to PBC bytecode, a platform-independent packfile format that could be pre-compiled and loaded directly. A minimal PIR program:
.sub 'main' :main
say "Hello, World!"
.end
And a recursive function showing parameters, typed temporaries and a call:
.sub 'factorial'
.param int n
if n > 1 goto recurse
.return (1)
recurse:
$I0 = n - 1
$I1 = 'factorial'($I0)
$I0 = n * $I1
.return ($I0)
.end
.sub 'main' :main
$I0 = 'factorial'(10)
say $I0
.end
The same thing in PASM is visibly lower-level: registers are named explicitly and control flow is by labels and branches.
set I0, 10
set I1, 1
loop:
mul I1, I1, I0
dec I0
if I0, loop
print I1
print "\n"
end
Runtime services
Beyond the opcode set (which covered arithmetic, strings, PMC manipulation, control flow, I/O and introspection), the runtime provided:
| Facility | Notes |
|---|---|
| Garbage collection | Several collectors over the project’s life; a generational collector (gms) was added in 3.2.0 (March 2011) and is referred to as the default GC in the 7.x release notes, with --gc=ms, ms2 and inf selectable at configure time |
| Objects | Classes, roles, attributes and multiple inheritance in the PDD 15 metamodel; NQP later brought its own 6model on top |
| Exceptions | PDD 23 exception handlers with resumable exceptions, used for die, control flow and language-level exceptions |
| Multiple dispatch | PDD 27 multi-subs and multi-methods selected on PMC types |
| Native Call Interface | Signature-based calls into C libraries without writing glue; the runtime library shipped bindings for OpenGL, SDL, ncurses, PCRE, OpenSSL and PostgreSQL |
| Threads | Hybrid OS/green threads with a --numthreads option from 4.11.0 (December 2012) |
| Embedding | A C API (parrot/api.h, PDD 10) for hosting the VM in other programs, exercised by mod_parrot |
| Tools | parrot_debugger, a profiling runcore, pbc_dump, pbc_merge, and the parrot_config query tool |
Compiler toolkit
PGE parsed Perl 6 rules into match objects and could run as recursive-descent or operator-precedence parser within one grammar; PCT’s HLL::Compiler class took a grammar and actions and produced a compiler that could be run interactively, on files or embedded; NQP (and from 2009 nqp-rx, which added Perl 6 regex support to the language itself) supplied the action language. Winxed, Julián Albo’s JavaScript-like language whose compiler was written in Winxed and emitted PIR, was added to the tree in 2011 and became the language much of Parrot’s own tooling was written in.
Evolution
Parrot’s history divides into four phases. The design phase (2001-2005) under Sugalski produced the architecture, the PDDs and the first two books, but releases were irregular and the languages were prototypes. The NLnet-funded, monthly-release phase (2005-2009) under Tötsch, Salzenberg and then Randal produced PGE, PCT, NQP, Rakudo and the Foundation, culminating in 1.0 and its API stability promises. The post-1.0 phase (2009-2012) was one of ambitious refactoring: the i386 JIT was removed in 1.7.0 (October 2009) to be rewritten; 2.5.0 (June 2010) began “Lorito”, a plan to rebuild the ops on a minimal self-hosting core (“M0”) that could be JIT-compiled; 3.0.0 (January 2011) delivered a new embedding API; and 4.11.0 (December 2012) delivered hybrid threads. Randal left for Canonical in 2010 and Christoph Otto became architect, restructuring the project into teams because “the architect position has had a bus number of one”. The maintenance phase (2013-2016) under Bruce Gray and Reini Urban kept the monthly cadence alive - with two scheduled releases skipped in 2013, “pining for the fjords” - while the commit count fell from 7,800 in 2008 to a few hundred a year.
The decisive change was outside the project. Rakudo gained a JVM backend in 2013, and at a YAPC::NA hackathon the same year Jonathan Worthington unveiled MoarVM, which he had been building privately - announced on his blog on 31 May 2013 - as a leaner runtime for NQP and Rakudo, with an internal model closer to 6model than Parrot’s. Within two years MoarVM had “almost entirely replaced Parrot as the language’s runtime of choice” (Worthington’s 2021 VMIL keynote). On 16 February 2015 Patrick Michaud announced that Rakudo would suspend Parrot support after 2015.02: the list refactor, native shaped arrays and grapheme-based strings needed features Parrot lacked, “most of the current userbase had switched to MoarVM”, and no developer wanted to keep the backend alive. Rakudo’s first stable release that December ran on MoarVM. Parrot 8.1.0 followed on 16 February 2016 as the final release; NQP deleted its Parrot backend that August, and Debian dropped the package the same month.
Current Relevance
Parrot is discontinued. README.pod has carried the notice “The Parrot VM is no longer being actively developed” since 25 August 2021, parrot.org no longer serves pages (docs mirrors survive at parrot.github.io), and the Parrot Foundation was dissolved in 2014. The source still builds: the PLATFORMS file records successful builds during 2015 (most dated December) on macOS (clang and gcc), Linux (gcc 4/5 and clang 3), Windows (MSVC 10 and 12, MinGW) and Cygwin, with 2015 reports for MIPS, FreeBSD 10, OpenBSD 4.9 and OpenSolaris 11 and older (2010-2011) reports for ARM, PowerPC, SPARC64, NetBSD and Intel’s icc; the project’s declared “core platforms” were Linux, Win32, OS X, Cygwin, FreeBSD, NetBSD, OpenBSD and Solaris on x86 (32- and 64-bit) plus PPC for OS X. In December 2025 Reini Urban, the last release manager, made some 44 commits cleaning up warnings for modern compilers, fixing memory leaks under AddressSanitizer and adding GitHub Actions CI, under a ChangeLog heading for an unreleased 8.3.0 - so the code compiles on a 2026 toolchain, even though nothing runs on it in production. The repository (617 stars, 146 forks) is the primary source for the project’s history; the ChangeLog goes back to the first commit of 29 August 2001.
What survived is elsewhere. NQP, born as Parrot’s action language, is the implementation language of Rakudo on MoarVM, the JVM and JavaScript. PGE’s approach to Perl 6 grammars lives on in Raku’s grammar engine. MoarVM is itself a register-based VM whose early design was informed by what Parrot got right and wrong. And Sugalski’s post-mortem, Otto’s “bus number of one” post and Michaud’s suspension announcement are cited whenever people discuss why language runtimes succeed or fail.
Why It Matters
Parrot was the first serious attempt at a shared runtime for dynamic languages, predating Microsoft’s DLR (2007) and the JVM’s invokedynamic (2011); its PMC vtables and HLL namespaces were an early answer to the question of how a Python list and a Perl array can coexist in one heap. It normalised the register-machine design for scripting-language VMs at a time when the stack machine was the default (Lua 5.0 made the same choice independently in 2003, and Android’s Dalvik followed in 2008). It pioneered a monthly release cadence with rotating release managers and quarterly “supported” releases years before that became common practice. And for the Perl 6 project it was indispensable: without a VM to target, and without PGE, PCT and NQP, there would have been no Rakudo - the Perl 6 Weekly’s farewell in 2016 called Parrot “one of the giants on whose shoulders Rakudo Perl 6 is standing”. Its failure to become the universal runtime it aimed to be is the other half of the lesson: a volunteer project that tries to serve every language at once, while the one language that needs it most is still being designed, can find that its most important user outgrows it.
Further Reading
- Repository: github.com/parrot/parrot -
docs/parrothist.pod(every release with date, name and manager),docs/pdds/(the design documents),docs/book/pir/(the PIR book),ChangeLog,CREDITS,DONORS.pod,PLATFORMS - Documentation mirrors: parrot.github.io/parrot-docs7/7.3.0/html/ and the 0.x-6.x series under
parrot-docs0…parrot-docs6 - Simon Cozens, “Programming Parrot” (perl.com, 1 April 2001) and “Parrot: Some Assembly Required” (perl.com, 18 September 2001)
- Dan Sugalski, Squawks of the Parrot (sidhe.org/oldblog): “The Python vs Parrot challenge is on!” (14 July 2003) and “The Parrot post-mortem” (20 October 2005); “Passing on the hat” (perl6-internals, 21 March 2005); “Pies away anyway” (1 August 2004)
- Allison Randal, Dan Sugalski and Leopold Tötsch, Perl 6 Essentials (O’Reilly, 2003) and Perl 6 and Parrot Essentials (O’Reilly, 2004)
- NLnet, “Impact of Parrot grant” (nlnet.nl/project/parrot, 16 October 2007; project page last updated 9 November 2007) and press release “NLnet sponsors Parrot” (18 April 2005)
- Jeff Horwitz, “Introducing mod_parrot” (perl.com, 22 December 2004)
- Christoph Otto, “Parrot has a new architect. What now?” (reparrot.blogspot.com, 21 October 2010)
- Patrick Michaud, “Suspending Rakudo support for Parrot” (pmthium.com, 16 February 2015)
- Perl 6 Weekly, “2016.31 An End Of An Era” (1 August 2016)
- Jonathan Worthington, “MoarVM: A virtual machine for NQP and Rakudo” (6guts.wordpress.com, 31 May 2013) and “Reflections on a decade of MoarVM” (VMIL 2021 keynote abstract)
Timeline
Notable Uses & Legacy
Rakudo Perl 6 (2008-2015)
Rakudo, the main Perl 6 compiler, was written inside the Parrot repository as languages/perl6 until February 2009 and ran exclusively on Parrot until the JVM backend (2013) and MoarVM (2013-2014) arrived. Rakudo Star, the first Perl 6 distribution (29 July 2010), bundled Parrot; the Rakudo 2015.02 release was the last with Parrot support, and the 'Christmas' Perl 6.c release of December 2015 shipped on MoarVM
Parrot Compiler Toolkit, PGE and NQP
Patrick Michaud's PGE (2004) implemented Perl 6 rules as a parser generator on Parrot; PCT (June 2007) added PAST/POST tree classes and a driver so a grammar plus NQP action methods yields a working compiler; NQP ('Not Quite Perl', 2007) and its regex-capable successor nqp-rx (2009) were the languages those actions were written in. Rakudo, Pynie, Cardinal, Partcl, Lua on Parrot and the Squaak tutorial language were all built with this toolkit, and NQP outlived Parrot as the implementation language of Rakudo on MoarVM and the JVM
Lua on Parrot
François Perrad's Lua compiler, started in languages/lua in November 2005 and later moved to its own repository, was one of the three implementations Parrot's own languages page listed as most complete (with Rakudo and Winxed); Perrad also served as release manager for Parrot 1.1.0 in April 2009
Winxed
Julián Albo's Winxed (2009), a JavaScript-like language with a compiler written in Winxed that emits PIR, became the language of choice for Parrot's own utilities; a snapshot of the compiler has been built and installed with every Parrot release since 3.5.0 in June 2011
Partcl, Punie, Pynie and Cardinal
Will Coleda's Partcl (Tcl, from 2003), Allison Randal's Punie (Perl 1, 2005) and Pynie (Python, 2007, started by Michaud) and Kevin Tew's Cardinal (Ruby, 2006) were the flagship demonstrations of Parrot as a multi-language runtime; they lived in the languages/ directory until 1.0 (March 2009) sent them to separate repositories, and none became a primary implementation of its language
Amber for Parrot and mod_parrot
Roger Browne's Amber for Parrot (2005-2006), an Eiffel-and-Ruby-flavoured scripting language with Design by Contract, was written directly against the VM and is described on its own page on this site. Jeff Horwitz's mod_parrot embedded the Parrot interpreter in the Apache web server so that handlers could be written in PIR or in any Parrot-hosted language