ParaSail
ParaSail (Parallel Specification and Implementation Language) is S. Tucker Taft's pointer-free, pervasively parallel object-oriented language: every parameter, every operand of an expression and every iteration of a for loop is evaluated in parallel unless the program says otherwise, and the compiler rejects any code where that could produce a race. Designed in public on a blog from September 2009, first released as an alpha interpreter in October 2011 by Taft's company SofCheck and carried on at AdaCore after the two merged in January 2012, it grew an LLVM compiler written in ParaSail itself, a static analyser, and sibling front ends (Sparkel, Javallel, Parython and an Ada 202X prototype) that share its virtual machine. The last packaged release was 9.3 in June 2021; the sources moved to GitHub in 2022 and still receive occasional commits
Created by S. Tucker Taft - lead designer of Ada 95 and founder of SofCheck, Inc. (Burlington/Lexington, Massachusetts), who designed ParaSail as a solo, blog-documented project from September 2009; AdaCore's Director of Language Research after the SofCheck merger of January 2012, with AdaCore supporting the work thereafter. Justin Hendrick (a Cornell summer intern) wrote the first LLVM code generator in 2014; Olivier Henley created the GitHub repository in October 2022
ParaSail - the Parallel Specification and Implementation Language - is a programming language built on a single provocative bet: that the easiest way to write correct parallel programs is to remove the features that make parallelism dangerous. It has no pointers, no global variables, no parameter aliasing, no exceptions, no explicit threads or locks, and no garbage-collected heap. In exchange, it makes everything parallel by default - the operands of F(X) + G(Y) are evaluated concurrently, so are the parameters of a call, so are the iterations of a for loop - and the compiler proves, using only local analysis, that none of that concurrency can produce a race.
The language is the personal project of S. Tucker Taft, who led the design of Ada 95 and later became AdaCore’s Director of Language Research. He designed it in the open, one blog post at a time, beginning in September 2009; shipped a prototype compiler and virtual machine in October 2011; and kept developing it - as a research vehicle rather than a product - into the 2020s, along the way spawning three sibling languages (Sparkel, Javallel and Parython), an LLVM compiler written in ParaSail itself, and the prototypes for the lightweight parallelism that eventually entered the Ada 2022 standard. Its last packaged release was 9.3 in June 2021, but its sources live on GitHub and still see commits.
History and origins
A language designed on a blog (2009-2011)
Taft opened Designing ParaSail, a new programming language on 25 September 2009 with a post titled “Why design a new programming language?”. His answer was that “a well-designed programming language can result in more productive programmers building higher quality software”, above all in “high-integrity software, including both safety-critical software and high-security software”, and that the arrival of multicore chips demanded a language in which parallelism and formal annotations - “pre- and postconditions, liberal use of assertions and invariants” - were native rather than bolted on. The name, he explained, would have been “ParaSAIL” but for the risk of confusion with Stanford’s SAIL; he did not mind the echo, “as it was a very interesting language in its day”.
He was candid about the ancestry. ParaSail “steals liberally from other programming languages, including the ML series (SML, CAML, OCAML, etc.), the Algol/Pascal family (Algol, Pascal, Ada, Modula, Eiffel, Oberon, etc.), the C family (C, C++, Java, C#), and the region-based languages (especially Cyclone)”. The one deliberate break with that baseline was storage management: ParaSail “is intended to avoid ‘fine-granule’ garbage collection in favor of stack and region-based storage management”.
The blog then worked through the design in public, at a pace of several posts a month. Modules, interfaces and classes came first (28 September 2009), then “ParaSail has no global variables” (12 October) and “ParaSail’s implicit parallelism” (17 October), the three-way =? comparison operator, region-based storage (9 November), concurrent interfaces (11 November), universal types, physical units, enumerations, a full BNF (April 2010), and in May 2010 the post that became the language’s signature: “ParaSail without pointers?”. By the summer of 2010 there were an aflex/ayacc grammar and worked examples (N-queens, 17 July 2010); in August Taft decided there would be “no exceptions in ParaSail, but exitable multi-thread constructs”; and on 1 November 2010 he described the ParaSail Virtual Machine (PSVM) with its “picothread” scheduling.
The first public presentation was “An Introduction to ParaSail” at Ada-Europe 2010 in Valencia, given while Taft was still at SofCheck, the Massachusetts static-analysis company he had founded. The Ada User Journal reprinted an edited version of the blog in March 2011; a first complete draft reference manual followed on 8 May 2011; and Taft submitted a paper, “Designing ParaSail: A new language for race-free parallel programming”, to Onward! 2011 arguing that a solo, blog-based process “differs significantly from the more conventional process involving a language design team, or a language design committee” - and, with a nod to the camel, that committees produce humps.
From SofCheck to AdaCore (2011-2013)
In 2011 the language went on tour: a tutorial at Ada-Europe in Edinburgh (20 June), an introduction at OSCON in Portland (27 July), an Intel “Parallel Programming Talk” video, panels at SPLASH/OOPSLA and a tutorial and workshop at SIGAda 2011 in Denver, published as “Experimenting with ParaSail” in Ada Letters 31(3). The OSCON talk brought press: MIT Technology Review ran “New Language for Programming in Parallel” on 28 July 2011, describing ParaSail as looking “like a modified form of Java or C#” that “automatically splits a program into thousands of smaller tasks” and quoting Taft - “Everything is done in parallel by default, unless you tell it otherwise” - and eeNews Europe reported the same day that “SofCheck preps ParaSail parallel language”, describing SofCheck (Burlington, Mass.) as “led by chairman and chief technology officer Tucker Taft”. The promised software arrived on 3 October 2011: “the first, alpha, release of the ParaSail prototype Compiler and Virtual Machine”, with executables for Mac, Linux and Windows, distributed through the ParaSail Google Group.
On 10 January 2012 AdaCore and SofCheck merged. AdaCore acquired SofCheck’s static error-detection tools, its reusable Ada compiler front-end technology and “ParaSail, a new Parallel Specification and Implementation Language intended for high-reliability applications on multicore target platforms”; Taft was named AdaCore’s Director of Language Research, and the Ada sources of the ParaSail implementation carry AdaCore copyright headers beginning in 2012 (“Copyright (C) 2012-2013, AdaCore” in files untouched since, running to 2012-2022 in others). The alpha releases kept coming - rev 2.0 with full inheritance and polymorphism (February 2012), rev 3.0 with the ability to return or exit from inside a parallel construct and have the other picothreads shut down (July), rev 3.4 with lambda expressions (September), rev 3.6 as the first source release, rev 3.7 with a special map/reduce syntax and an optional Python-like layout (November), rev 3.8 with import clauses and an I/O library (January 2013). Taft’s article “ParaSail: Less is More with Multicore” ran on EE Times and embedded.com in June 2012, EEJournal interviewed him over lunch in Paris, and he presented at NEPLS (June 2012) and Microsoft Research (September 2012) and led an unsession on region-based storage at Strange Loop 2012.
A family of languages (2013-2016)
The parser was only ever a thin layer over the ParaSail semantic analyser and virtual machine, and in 2013 Taft began attaching other syntaxes to the same core. Rev 4.6 introduced Sparkel, “a parallel language inspired by SPARK subset of Ada”, presented at HILT 2013; release 5.1 on 21 November 2013 added Javallel (Java-like) and Parython (Python-like). “The ParaSail family of languages is growing,” the announcement said, and all four shared a rewritten region-based storage manager that “dramatically reduce[d] the contention between cores”. Rev 5.2 (February 2014) then re-implemented work stealing with a private deque per server thread.
The other big change of 2014 was compilation. Until then ParaSail had been interpreted. That summer Justin Hendrick, a Cornell intern, wrote an LLVM code generator - in ParaSail - and by 25 July “the compiler itself uses neither of these features, so it’s able to compile itself”. Rev 6.0 was the “first release with an llvm-based compiler”; 6.1 the first to pass the whole test suite; 6.5 (November 2015) added prototypes of the ParaScope static analyser; and 7.0 (November 2016) rewrote the compiler around virtual-register annotations in the PSVM code and automatic inlining.
Publication, Ada 202X and GitHub (2019-2026)
After a quiet stretch, release 8.0 (9 February 2019) brought an interactive debugger, fully checked pre- and postconditions and string interpolation, and on 1 February 2019 The Art, Science, and Engineering of Programming published Taft’s 32-page account of the language, “ParaSail: A Pointer-Free Pervasively-Parallel Language for Irregular Computations”, which he presented at the ‹Programming› conference in Genoa that April. Release 8.4 (October 2019) added “a very preliminary Ada202X front end, based on Sparkel”, and release 9.3 (June 2021) - the last packaged release - made Univ_Integer arbitrary-precision and taught the Ada front end parallel loops with chunking, parallel blocks and reduction expressions.
In July 2020 Taft wrote that his AdaCore job “went down to 60%” to free time for ParaSail and its siblings, a new blog, and “a new language on the drawing board, ParaDISO (Parallel Distributed, Incremental, Streamable Objects), for distributed/cloud computing”. On 28 October 2022 his colleague Olivier Henley imported the full sources into github.com/parasail-lang/parasail; the revision numbering switched to YY.MM (22.11) the following month; and the blog’s final post, “ParaSail now on GitHub”, appeared on 12 December 2024. Since then the repository has hosted Taft’s Ada 2022 Light-Weight Threading library (LWT, an Alire crate since 2025), a prototype hardware-description language called Phiddle, and steady small commits - 98 in 2025, a handful in 2026 through 18 August.
Design philosophy
Taft’s 2012 article opens with a top-ten list, “with apologies to David Letterman”, of “the biggest impediments to doing things efficiently and safely in a highly parallel multicore world”: global variables, a garbage-collected global heap, parameter aliasing, run-time exception handling, explicit threads, explicit lock/unlock, explicit wait/signal, race conditions, “and worst of all … Pointers”. ParaSail is what remains when all of them are removed. “In ParaSail, it is easier to write parallel algorithms than sequential ones. If sequential execution is needed, the programmer has to work harder.”
Three principles do most of the work:
- Safety through subtraction. The 2019 paper puts it plainly: “ParaSail achieves these goals largely through simplification of the language, rather than by adding numerous rules.” Functions cannot see global variables; two parameters may not alias if either is updatable;
varparameters use hand-off semantics borrowed from IBM’s Hermes, so a variable handed to one call cannot be touched by the caller or passed elsewhere until the call returns. With those rules, “expressions such asF(X) + G(Y)can be safely evaluated in parallel, without the compiler looking inside the bodies of the functions F or G”. - Parallel by default. Parameter evaluation, subexpressions and
forloops are unordered unless the program saysforward,reverseor usesthento sequence statements. Explicit parallelism is available too -||between statements andconcurrent loop- and the compiler verifies that explicitly parallel sections have no data interdependences. - Few concepts. The Ada-Europe 2010 bullet list reads: “Module, Type, Object, Operation. You get a Type by instantiating a Module (all Modules are ‘generic’). You get an Object by instantiating a Type.” Records, packages, classes, templates and containers are all the same thing, and user-defined types use the same syntax as built-in ones - the design principles in the Onward! paper include “the language should have one primary way to do something rather than two or three nearly equivalent ones” and “nonessential features should be eliminated, especially those that are error prone or complicate the testing or proof process”.
The most distinctive consequence is the pointer-free data model. Instead of pointers, ParaSail has expandable and shrinkable objects: a component declared optional may be null or may hold a whole sub-object, so a binary tree is a node with two optional children, and assignment copies values. Storage is managed by regions tied to scopes and reclaimed as a whole, with a “move” operator <== that transfers contents and leaves the source null. Taft’s related-work survey observes that “there are very few pointer-free languages currently under active development” - Fortran 77 and Algol 60 lacked pointers, SPARK omits them, Hermes eliminated them with high-level type constructors - and argues from “over six years of use by the author and a group of ParaSail users” that “it is possible to simultaneously simplify the language, support parallel programming with advanced data structures, and maintain flexibility and efficiency”.
Key features
Syntax
ParaSail reads like a cross between Ada and Java: Ada-style is ... end func Name bracketing and := assignment, C-style // comments, angle-bracket module parameters, and -> for a function’s result. The first program on the project’s website is:
import PSL::Short_Names::*, *
func Greetings() is
Println("Hello, World!")
end func Greetings
Semicolons at line ends are optional. Early versions of the language had no global standard output at all - a program received an IO object as a var parameter and wrote IO.Println(...), a form that survives, commented out, in the repository’s bmap.psl example and in the func Play_A_Game(var IO) examples of Taft’s introductory slides; the current standard library lets Println be called directly. Taft’s 2012 introductory article uses a recursive word counter to show pattern-like case alternatives, a -> Univ_Integer result and the way the two recursive calls in the last branch are, by default, evaluated in parallel:
func Word_Count
(S : Univ_String;
Separators : Countable_Set<Univ_Character> := [' '])
-> Univ_Integer is
// Return count of words separated by given set of separators
case Length(S) of
[0] => return 0; // Empty string
[1] =>
if S[1] in Separators then
return 0; // A single separator
else
return 1; // A single non-separator
end if;
[..] => // Multi-character string; divide and conquer
const Half_Len := Length(S)/2;
const Sum := Word_Count(S[1 .. Half_Len], Separators) +
Word_Count(S[Half_Len <.. Length(S)], Separators);
if S[Half_Len] in Separators
or else S[Half_Len+1] in Separators then
return Sum; // At least one separator at border
else
return Sum-1; // Combine words at border
end if;
end case;
end func Word_Count;
Modules, interfaces and classes
Every module has an interface (its visible operations and, for concrete modules, its components) and a class implementing it, separated by the keyword exports. All modules are generic: interface BMap<Key_Type is Ordered<>; Element_Type is Assignable<>> is instantiated as BMap<Key_Type => Univ_Integer, Element_Type => Univ_String>. Operators are ordinary operations named by string - op "[]"() -> BMap creates an empty map, and =? is the single comparison an Ordered type must supply, from which ==, <, >= and the rest are derived. Modules can extends one another (single implementation inheritance) and implements several interfaces; a polymorphic type is written T+ and can hold any object whose type extends T. A concurrent module has operations marked locked (serialized) or queued (which wait on a dequeue condition, as in the dining-philosophers example that opens the project’s readme, where Pick_Up_Fork is queued until F.Is_Available).
Pointer-free data structures
Types may be recursive so long as the recursive component is optional. The map implementation in the reference examples is a binary tree in which insertion walks the tree with for M => BMap.Tree loop ... continue loop with M.Left, and if it reaches a null slot simply assigns a new node into it: M := (Key => Key, Value => Value, Left => null, Right => null). Deletion moves a subtree up with M <== M.Right. There is no allocation call, no free, and no way to create an alias.
Parallelism
- Implicit:
Word_Count(...) + Word_Count(...)runs both calls in parallel;for I in 1..N loopiterations are unordered unlessforwardorreverseis given. - Explicit:
concurrent loop, and statements separated by||.thenforces sequencing. - Map/reduce:
(for I in 1 ..< 2*N {I mod 2 == 1} => <0> + I)sums the odd integers below2N, with{...}as an iterator filter and<0>the initial accumulator; container comprehensions such as[for each E of Vec {E < Mid} => E]give a three-line functional quicksort. - Exitable parallel constructs: a
returnorexit loop with Xfrom inside a concurrent loop terminates the sibling picothreads, so “racing” searches are natural. - Implementation: the front end decides where to spawn picothreads and emits PSVM nested blocks; the interpreter and the compiled runtime map picothreads onto a pool of heavyweight server threads by work stealing, each server keeping a LIFO private deque and stealing FIFO from others. The project’s own numbers are relative: the rev 4.9 storage-manager rewrite “produced an approximate two times speed-up” and rev 5.2’s work-stealing rewrite “another two times speedup … thereby speeding up execution by four times or more since rev 4.8”, figures the project reported from its own test programs, without published benchmark details.
Annotations and universal types
Preconditions, postconditions and assertions are written in braces - func Square(N : Univ_Integer {N >= 0}) -> Univ_Integer - and since rev 4.7 may also be written {> ... <}. Where the compiler cannot prove an annotation it inserts a run-time check, and since release 8.0 a failed check drops the interpreter into an interactive debugger. Literals belong to universal types (Univ_Integer, Univ_Real, Univ_String, Univ_Character and #red-style Univ_Enumeration) that convert implicitly to any user type providing the right operations. There are no exceptions; errors that other languages raise at run time - null dereference, uninitialized data, out-of-range indexing, overflow, dangling references, races - are meant to be rejected at compile time.
Evolution
| Release | Date | Milestone |
|---|---|---|
| First alpha | 3 Oct 2011 | First prototype compiler and virtual machine (Mac, Linux, Windows) |
| Rev 2.0 | 5 Feb 2012 | Full inheritance and polymorphism (extends, T+) |
| Rev 3.0 | 22 Jul 2012 | Exit/return from inside parallel constructs |
| Rev 3.4-3.8 | Sep 2012 - Jan 2013 | Lambdas, first source release, map/reduce syntax, import clauses, I/O library |
| Rev 4.6 | 2013 | Sparkel front end |
| 5.1 | 21 Nov 2013 | Javallel and Parython; rewritten region storage manager |
| 5.2-5.3 | Feb-Apr 2014 | New work-stealing scheduler |
| 6.0-6.5 | 2014-Nov 2015 | LLVM compiler written in ParaSail; ParaScope analyser |
| 7.0 | 2 Nov 2016 | Compiler rewrite with virtual registers and inlining |
| 8.0 / 8.4 | 9 Feb / 31 Oct 2019 | Debugger, checked contracts, string interpolation; Ada 202X front end |
| 9.3 | Jun 2021 | Arbitrary-precision Univ_Integer; Ada 202X parallel loops and blocks; last packaged release |
| 22.11 | Nov 2022 | YY.MM numbering; sources on GitHub |
The syntax shifted several times in the early years - the 2011 Ada User Journal reprint warns that “some of the syntactic details have been changed over time”, and there were posts titled “Another slight shift in syntax” (July 2011) and “Everything in a func?”. Zero-based indexing for Vector and Univ_String arrived in July 2012; the PSL::Core / PSL::Containers library hierarchy in January 2013; {> <} annotation brackets and optional end labels in September 2013; string interpolation in 2019. The toolchain grew from a single-threaded interpreter to a multi-threaded VM (rev 1.5), then to a self-hosting LLVM compiler, a static analyser, and an interactive debugger.
Current relevance
ParaSail is dormant as a released product and alive as a research codebase. The last zip release is 9.3 from June 2021 (the parasail-lang.org page, a frame around adacore.github.io/ParaSail, still advertises 8.4); sparkel.org, which once hosted the sources, no longer resolves; the Google Group appears quiet; and the blog ended in December 2024 with a pointer to GitHub. But the GitHub repository is where Taft works: it received 98 commits in 2025 and continued into 2026 with Ada-front-end grammar work, new examples and build guides, and it is home to the LWT library, which is a live Alire crate used by the Ada Rapporteur Group’s GCC prototype of the Ada 2022 parallel syntax. There is no official Docker image; building from source needs GNAT, aflex/ayacc (bundled) and, for the compiler, LLVM. Pygments has shipped a ParaSail lexer since version 2.1 (January 2016), from a pull request the project submitted in 2014.
The language never acquired an industrial user base and was not designed to; from the outset Taft called it a place to “actually get the ideas down onto paper”, and the 2019 paper’s evidence is “use by the author and a group of ParaSail users”. Its practical legacy is in Ada: the Ada 2022 parallel loops, parallel blocks, chunking and reduction expressions were designed by Taft after a decade of ParaSail experience, prototyped in the ParaSail toolset’s Ada 202X front end, and are implemented today on top of a work-stealing scheduler that is a direct descendant of the PSVM’s.
Why it matters
ParaSail is the most thorough modern experiment in pointer-free programming. Rust reached memory and race safety by adding an ownership discipline to pointers; ParaSail asked what happens if you simply take pointers away and give programmers expandable objects and regions instead. Taft’s answer, worked out in over a hundred blog posts and a decade of implementation, was that surprisingly little is lost - trees, maps, graphs and hash tables all appear in the examples - and that what is gained is a language in which the compiler can parallelize any expression without interprocedural analysis. His own 2013 comparison, “Systems Programming in the Distributed, Multicore World with Go, Rust, and ParaSail” (Embedded Systems Conference, April 2013), and the HILT 2014 paper on safe parallelism in Ada both treat it as one of the three serious new attempts at safe parallel systems programming of its generation.
It is also a rare document of how a language gets designed. Because Taft wrote every decision down as he made it - the arguments for and against exceptions, the reasoning behind =?, the shift to zero-based indexing, the choice of regions over garbage collection - the ParaSail blog is a complete, dated record of one experienced designer’s process, and his Onward! paper on “blog-based language design” makes the case for doing it that way. For anyone interested in how the safety ideas of Ada, SPARK and the ML family might be recombined for multicore hardware, ParaSail remains the clearest worked example.
Timeline
Notable Uses & Legacy
The ParaSail compiler itself
The LLVM code generator (lib/compiler.psl) is written in ParaSail and has been self-hosting since July 2014, when the summer-intern project reached the point where 'the compiler itself uses neither of these [unsupported] features, so it's able to compile itself'. Releases ship a bootstrapped 'compiler.exe' for Linux and Mac; the 2019 paper reports that running the compiler back end over the roughly 10,000-line ('10k lines') run-time library took 2:48 wall-clock single-threaded versus 1:31 using all four virtual cores of a dual-core hyper-threaded 2.5 GHz Intel i5 (averaged over two runs, with CPU time rising from 164 to 290 seconds) - 'almost a two-times speed-up', because the compiler's own operations are compiled in parallel
ParaScope static analyser
A 'static catcher of programming errors' written in ParaSail (lib/parascope.psl), based on a variant of abstract interpretation, that analyses PSVM instructions and is intended to report nullness, unused-variable and other errors at compile time and to tell the compiler where run-time checks are needed. It shipped as a prototype from release 6.5 (November 2015) and is invoked with bin/scope.csh
Sparkel, Javallel, Parython and the Ada 202X prototype
Four alternative front ends that reuse ParaSail's abstract syntax tree, semantic analysis, PSVM and back ends to give SPARK/Ada, Java and Python a pointer-free, pervasively parallel dialect (Sparkel from rev 4.6, Javallel and Parython from release 5.0 in November 2013, Ada202X from 8.4 in 2019). The Ada 202X interpreter (a2xi) was used to try out the parallel loops, chunking, parallel blocks and reduction expressions that entered the Ada 2022 standard
LWT - Light-Weight Threading for Ada 2022
Taft's Ada library, developed inside the ParaSail repository from October 2023 and published on Alire (lwt 1.2.0, November 2025), implements the Ada 2022 parallel features with plug-in OpenMP and work-stealing schedulers modelled on ParaSail's picothread scheduler; the Ada Rapporteur Group's gcc-mirror prototype of the 'parallel' syntax uses it for threading
Phiddle hardware-description prototype and Pygments
In December 2024 Taft began 'Phiddle', an HDL embedded in ParaSail (hdl_in_parasail), whose mux example was working by January 2025. Outside the project, Pygments has carried a ParaSailLexer (pygments.lexers.parasail) since version 2.1 of January 2016, from a pull request (#381) the project submitted in 2014, so ParaSail code is syntax-highlighted on GitHub, Sphinx and other Pygments-based sites