Laurel User Guide

4.4. Assignment and update operators🔗

Assignment targets a local or a field. A multi-assignment unpacks a call with several outputs; its right-hand side must be such a call, and its targets are positional. A target introduced with var declares a new local, and a bare target updates an existing one.

procedure triple() returns (a: int, b: int, c: int)
  opaque
{
  a := 1; b := 2; c := 3
};

composite Holder { var field: int }

procedure assignments()
  opaque
{
  var x: int := 3;
  var obj: Holder := new Holder;
  obj#field := 4;
  assign var p: int, x, var r: int := triple();
  assert p == 1
};

The Java-style increment and compound-assignment forms are also available. The prefix forms yield the new value and the postfix forms the old one:

procedure updateOperators()
  opaque
{
  var x: int := 0;
  ++x;
  x++;
  --x;
  x--;
  x += 2;
  var s: string := "pre";
  s ^= "suffix";
  assert x == 2
};

Each compound form means what it looks like: x op= y is x := x op y. Increment and decrement are currently restricted to int and to constrained types over int. Both families accept a field lvalue, but an update operator on a field duplicates the receiver expression, so keep the receiver side-effect-free — bind it to a local first if it is not.