Pulse: Proof-oriented Programming in Concurrent Separation Logic

Many F* projects involve building domain-specific languages with specialized programming and proving support. For example, Vale supports program proofs for a structured assembly language; Low* provides effectful programming in F* with a C-like memory model; EverParse is a DSL for writing low-level parsers and serializers. Recently, F* has gained new features for building DSLs embedded in F* with customized syntax, type checker plugins, extraction support, etc., with Pulse as a showcase example of such a DSL.

Pulse is a new programming language embedded in F*, inheriting many of its features (notably, it is higher order and has dependent types), but with built-in support for programming with mutable state and concurrency, with specifications and proofs in Concurrent Separation Logic.

As a first taste of Pulse, here’s a function to increment a mutable integer reference.

fn incr (x:ref int)
requires pts_to x 'i
ensures pts_to x ('i + 1)
{
    let v = !x;
    x := v + 1;
}

And here’s a function to increment two references in parallel.

fn par_incr (x y:ref int)
requires pts_to x 'i ** pts_to y 'j
ensures pts_to x ('i + 1) ** pts_to y ('j + 1)
{
   par (fun _ -> incr x)
       (fun _ -> incr y)
}

You may not have heard about separation logic before—but perhaps these specifications already make intuitive sense to you. The type of incr says that if “x points to ‘i” initially, then when incr returns, “x points to ‘i + 1”; while par_incr increments the contents of x and y in parallel by using the par combinator.

Concurrent separation logic is an active research area and there are many such logics out there, all with different tradeoffs. Pulse’s logic is based on a logic called SteelCore and a prior DSL built on top of SteelCore called Steel. SteelCore itself builds on ideas from Iris and Hoare Type Theory. But, you should not need to know much about any of this research— we’ll start from the basics and explain what you need to know about concurrent separation logic to start programming and proving in Pulse. Additionally, Pulse is an extension of F*, so all you’ve learned about F*, lemmas, dependent types, refinement types, etc. will be of use again.

Note

Why is it called Pulse? Because it’s based on a logic called Steel, and one of the authors and his daughter are big fans of a classic reggae band called Steel Pulse. We wanted a name that was softer than Steel, and, well, a bit playful. So, Pulse!