Skip to content

Commit

Permalink
wisl formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasLoow committed Dec 11, 2024
1 parent 649f1e0 commit d548b7c
Showing 1 changed file with 63 additions and 41 deletions.
104 changes: 63 additions & 41 deletions sphinx/wisl/lab.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@

Initial Lab
===========

Welcome to the first Gillian lab! In this lab, you'll be using Gillian and its :doc:`debugger </debugger>` to add missing proof tactics to while programs and verify them with :doc:`/wisl/index`.

You are provided with 2 files: ``sll.wisl`` and ``dll.wisl``, which contain predicates, lemmas and functions. The goal is to use WISL and its debugger to insert the right proof tactics for every function to successfully verify.
You are provided with 2 files: ``sll.wisl`` and ``dll.wisl``, which contain predicates, lemmas and functions. The goal is to use WISL and its debugger to insert the right proof tactics for every function to successfully verify.
Note that in practice, Gillian can infer a lot of these annotations on its own; for this lab, we disable this by using Gillian's "manual" mode.
For every while loop, the invariant is already provided.


Getting started
---------------

Expand All @@ -23,7 +21,7 @@ First off, make sure you have the necessary prerequisites:
Then, clone the lab files and open the folder in VSCode:

.. code-block:: text
$ git clone https://github.com/GillianPlatform/gillian-lab.git --branch WEBSITE --depth 1
$ code gillian-lab
Expand All @@ -48,55 +46,79 @@ Note that you can quickly return to a point in the execution after modifying the
Proof tactics
-------------

| **Folding & unfolding predicates**
| You can fold a predicate with:
| ``[[ fold pred_name(param1, ... paramN) ]]``
| And similarly unfold a predicate with:
| ``[[ unfold pred_name(param1, ... paramN) ]]``
| **Applying lemmas**
| A number of lemmas are provided for you; you can apply them like so:
| ``[[ apply lemma_name(param1, ... paramN) ]]``
| **Logical assertions**
| You can assert a logical condition with:
| ``[[ assert someCondition ]]``
| Some proofs will require you to use ``assert`` to bind variables. For example, let's imagine that you need to apply a lemma, and one of the parameters is the value contained in a cell at the address in variable ``t``, i.e. your state contains ``t -> ?``, and you want to apply ``some_lemma(t, ?)``. The problem is, you do not have any program or logical variable available that contains the right value to use as the second parameter. One solution would be to use a program variable:
| ``v := [t];``
| ``[[ apply some_lemma(t, v) ]];``
| However, modifying the program for the sake of the proof is against the spirit of things! That's when ``assert {bind: ..}`` comes in:
| ``[[ assert {bind: #v} (t -> #v) ]];``
| ``[[ apply some_lemma(t, #v) ]];``
| **Conditionally applying tactics**
| You can use if/else in a logical context, like so:
| ``[[ if (condition) { .. } { .. } ]]``
| **Loop invariants**
| Loop invariants are provided for you where necessary. They are declared like so:
| ``[[ invariant {bind: #x, #y} P(#x, #y) ]]``
**Folding & unfolding predicates.**
You can fold a predicate with:

.. code-block:: text
[[ fold pred_name(param1, ..., paramN) ]]
And similarly unfold a predicate with:

.. code-block:: text
[[ unfold pred_name(param1, ..., paramN) ]]
**Applying lemmas.**
A number of lemmas are provided for you; you can apply them like so:

.. code-block:: text
[[ apply lemma_name(param1, ..., paramN) ]]
**Logical assertions.**
You can assert a logical condition with:

.. code-block:: text
[[ assert someCondition ]]
Some proofs will require you to use ``assert`` to bind variables. For example, let's imagine that you need to apply a lemma, and one of the parameters is the value contained in a cell at the address in variable ``t``, i.e. your state contains ``t -> ?``, and you want to apply ``some_lemma(t, ?)``. The problem is, you do not have any program or logical variable available that contains the right value to use as the second parameter. One solution would be to use a program variable:

.. code-block:: text
v := [t];
[[ apply some_lemma(t, v) ]];
However, modifying the program for the sake of the proof is against the spirit of things! That's when ``assert {bind: ..}`` comes in:

.. code-block:: text
[[ assert {bind: #v} (t -> #v) ]];
[[ apply some_lemma(t, #v) ]];
**Conditionally applying tactics.**
You can use if/else in a logical context, like so:

.. code-block:: text
[[ if (condition) { ... } { ... } ]]
**Loop invariants.**
Loop invariants are provided for you where necessary. They are declared like so:

.. code-block:: text
[[ invariant {bind: #x, #y} P(#x, #y) ]]
Common issues
-------------

Syntax
^^^^^^

**Syntax.**
The while language syntax can be a bit tricky:

* Put everything in parentheses! Operator precedence may be unpredictable.
* There is a semi-colon *between* each command inside a block, but *not at the end* (e.g. the last statement in an if-else block).
* Logical commands are surrounded by ``[[ .. ]]``.

Automatic unfolding in preconditions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Automatic unfolding in preconditions.**
Even in manual mode, Gillian will automatically unfold any predicate in the precondition of a function if it is not recursive.

In particular, the ``dlist`` predicate gets unfolded into its ``dlseg`` definition automatically.

Folding a list with one element
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Folding a list with one element.**
You may be having trouble trying to fold ``SLL`` with a single value, i.e. ``SLL(x, [v])``. This can go wrong because Gillian can't find the base case, ``SLL(null, [])``. Since the base case doesn't require any resources from your state, you're free to fold it from nothing, like so:

.. code-block:: text
| You may be having trouble trying to fold ``SLL`` with a single value, i.e. ``SLL(x, [v])``. This can go wrong because Gillian can't find the base case, ``SLL(null, [])``. Since the base case doesn't require any resources from your state, you're free to fold it from nothing, like so:
| ``[[ fold SLL(null, []) ]];``
[[ fold SLL(null, []) ]];

0 comments on commit d548b7c

Please sign in to comment.