Skip to content

CameLIGO: Add `mut`ability , `for` loops, and `while` loops

Alistair O'Brien requested to merge ajob410/cameligo-let-mut into dev

Motivation and Context

This is part of the ongoing work to improve CameLIGO's support for mutable programs.

This MR aims to implement add:

  • a let mut (a la Rust) construct and an assignment operator x := e for mutable variables.
  • for loops
  • for .. in .. loops
  • while loops

Description

We update CameLIGO's CST by adding the following nodes:

  • ELetMutIn
  • EAssign
  • EFor
  • EForIn
  • EWhile

The lexer and parser are updated, adding the following keywords and symbols (thanks to @rinderkn for helping me out!):

  • mut
  • for
  • while
  • do
  • done
  • to
  • downto
  • :=

The abstractors were trivially updated to support the extended CST.

Design notes:

  • We chose to support let mut instead of let x = ref 0 in ... for the following reasons:

    1. Users from OCaml will not confuse (second class) mutable variables with first class references (which OCaml provides)
    2. Transpilation from OCaml is not too poorly affected by this choice. Since we can use let%mut x = e in e in OCaml to encode this construct.
  • CameLIGO's parser levels (hierarchy) for expressions was updated to permit x := 1, 2, 3 to be parsed as x := (1, 2, 3) (as in OCaml).

  • We added a for .. in loop to support iteration over collections without the restriction on mutability becoming an issue to users.

    For example, the following wouldn't typecheck (since the anonymous function captures the mutable variable i):

      let iteri f xs = 
        let mut i = 0 in
        List.iter (fun x -> 
          begin
            f i x;
            i := i + 1 
          end)
          xs

    However, the following does typecheck:

      let iteri f xs =
        let mut i = 0 in 
        for x in xs do
          f i x;
          i := i + 1
        done
  • downto-loops are currently unsupported (raises an error in the abstractor). This is because negative increments are incorrectly compiled in our E_for construct.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Performance improvement (non-breaking change that improves performance)
  • None (change with no changelog)

Changelog

Add mutable variables, the assignment operator, for loops, and while loops to CameLIGO.

let do_something g n = 
  let mut x = 1 in
  for j = 1 to n do
    while x < 10 do
      x := g i j x;
    done
  end;
  x

Checklist:

  • Changes follow the existing coding style (use dune @fmt to check).
  • Tests for the changes have been added (for bug fixes / feature).
  • Documentation has been updated.
  • Changelog description has been added (if appropriate).
  • Start titles under ## Changelog section with #### (if appropriate).
  • There is no image or uploaded file in changelog
  • Examples in changed behaviour have been added to the changelog (for breaking change / feature).
Edited by Alistair O'Brien

Merge request reports