Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update types of indices to be u64 #92

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/examples/add_two_array.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
unsigned int array_read_two (unsigned int *p, int n, int i, int j)
unsigned int array_read_two (unsigned int *p, unsigned long n, unsigned long i, unsigned long j)
/* --BEGIN-- */
/*@ requires take a1 = each(i32 k; 0i32 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
0i32 <= i && i < n;
0i32 <= j && j < n;
/*@ requires take a1 = each(u64 k; 0u64 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
0u64 <= i && i < n;
0u64 <= j && j < n;
j != i;
ensures take a2 = each(i32 k; 0i32 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
ensures take a2 = each(u64 k; 0u64 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
a1 == a2;
return == a1[i] + a1[j];
@*/
Expand Down
8 changes: 4 additions & 4 deletions src/examples/array_load.broken.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
int read (int *p, int n, int i)
/*@ requires take a1 = each(i32 j; 0i32 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) };
0i32 <= i && i < n;
ensures take a2 = each(i32 j; 0i32 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) }; @*/
int read (int *p, unsigned long n, unsigned long i)
/*@ requires take a1 = each(u64 j; 0u64 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) };
0u64 <= i && i < n;
ensures take a2 = each(u64 j; 0u64 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) }; @*/
{
return p[i];
}
13 changes: 7 additions & 6 deletions src/examples/array_load.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
int read (int *p, int n, int i)
/*@ requires take a1 = each(i32 j; 0i32 <= j && j < n) {
int read (int *p, unsigned long n, unsigned long i)
/*@ requires take a1 = each(u64 j; 0u64 <= j && j < n) {
Owned<int>(array_shift<int>(p,j)) };
0i32 <= i && i < n;
ensures take a2 = each(i32 j; 0i32 <= j && j < n) {
0u64 <= i && i < n;
n > 0u64;
ensures take a2 = each(u64 j; 0u64 <= j && j < n) {
Owned<int>(array_shift<int>(p,j)) }; @*/
{
/*@ extract Owned<int>, i; @*/
return p[i];
/*@ extract Owned<int>, 0u64; @*/
return p[0];
}
8 changes: 4 additions & 4 deletions src/examples/array_load2.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
int read (int *p, int n, int i)
/*@ requires take a1 = each(i32 j; 0i32 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) };
0i32 <= i && i < n;
ensures take a2 = each(i32 j; 0i32 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) };
int read (int *p, unsigned long n, unsigned long i)
/*@ requires take a1 = each(u64 j; 0u64 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) };
0u64 <= i && i < n;
ensures take a2 = each(u64 j; 0u64 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) };
a1 == a2;
return == a1[i];
@*/
Expand Down
10 changes: 5 additions & 5 deletions src/examples/init_array.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
void init_array (char *p, unsigned int n)
/*@ requires take a1 = each(u32 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
ensures take a2 = each(u32 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
void init_array (char *p, unsigned long n)
/*@ requires take a1 = each(u64 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
ensures take a2 = each(u64 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
@*/
{
unsigned int j = 0;
unsigned long j = 0;
while (j < n)
/* --BEGIN-- */
/*@ inv take ai = each(u32 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
/*@ inv take ai = each(u64 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
{p} unchanged; {n} unchanged;
@*/
/* --END-- */
Expand Down
12 changes: 6 additions & 6 deletions src/examples/init_array2.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
void init_array2 (char *p, unsigned int n)
/*@ requires take a1 = each(u32 i; i < n) { Block<char>( array_shift<char>(p, i)) };
ensures take a2 = each(u32 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
void init_array2 (char *p, unsigned long n)
/*@ requires take a1 = each(u64 i; i < n) { Block<char>( array_shift<char>(p, i)) };
ensures take a2 = each(u64 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
@*/
{
unsigned int j = 0;
unsigned long j = 0;
while (j < n)
/* --BEGIN-- */
/*@ inv take al = each(u32 i; i < j) { Owned<char>( array_shift<char>(p, i)) };
take ar = each(u32 i; j <= i && i < n) { Block<char>( array_shift<char>(p, i)) };
/*@ inv take al = each(u64 i; i < j) { Owned<char>( array_shift<char>(p, i)) };
take ar = each(u64 i; j <= i && i < n) { Block<char>( array_shift<char>(p, i)) };
{p} unchanged; {n} unchanged;
j <= n;
@*/
Expand Down
20 changes: 10 additions & 10 deletions src/examples/init_array_rev.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
void init_array2 (char *p, unsigned int n)
/*@ requires take a1 = each(u32 i; i < n) { Block<char>( array_shift<char>(p, i)) };
n > 0u32;
ensures take a2 = each(u32 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
void init_array2 (char *p, unsigned long n)
/*@ requires take a1 = each(u64 i; i < n) { Block<char>( array_shift<char>(p, i)) };
n > 0u64;
ensures take a2 = each(u64 i; i < n) { Owned<char>( array_shift<char>(p, i)) };
@*/
{
unsigned int j = 0;
unsigned long j = 0;
while (j < n)
/* --BEGIN-- */
/*@ inv take al = each(u32 i; i < n-j) { Block<char>( array_shift<char>(p, i)) };
take ar = each(u32 i; n-j <= i && i < n) { Owned<char>( array_shift<char>(p, i)) };
/*@ inv take al = each(u64 i; i < n-j) { Block<char>( array_shift<char>(p, i)) };
take ar = each(u64 i; n-j <= i && i < n) { Owned<char>( array_shift<char>(p, i)) };
{p} unchanged; {n} unchanged;
0u32 <= j && j <= n;
0u64 <= j && j <= n;
@*/
/* --END-- */
{
/* --BEGIN-- */
/*@ extract Block<char>, n-(j+1u32); @*/
/*@ extract Owned<char>, n-(j+1u32); @*/
/*@ extract Block<char>, n-(j+1u64); @*/
/*@ extract Owned<char>, n-(j+1u64); @*/
/* --END-- */
p[n-(j+1)] = 0;
j++;
Expand Down
10 changes: 5 additions & 5 deletions src/examples/swap_array.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
void swap_array (int *p, int n, int i, int j)
void swap_array (int *p, unsigned long n, unsigned long i, unsigned long j)
/* --BEGIN-- */
/*@ requires take a1 = each(i32 k; 0i32 <= k && k < n) { Owned<int>(array_shift<int>(p,k)) };
0i32 <= i && i < n;
0i32 <= j && j < n;
/*@ requires take a1 = each(u64 k; 0u64 <= k && k < n) { Owned<int>(array_shift<int>(p,k)) };
0u64 <= i && i < n;
0u64 <= j && j < n;
j != i;
ensures take a2 = each(i32 k; 0i32 <= k && k < n) { Owned<int>(array_shift<int>(p,k)) };
ensures take a2 = each(u64 k; 0u64 <= k && k < n) { Owned<int>(array_shift<int>(p,k)) };
a2 == a1[i: a1[j], j: a1[i]];
@*/
/* --END-- */
Expand Down
20 changes: 10 additions & 10 deletions src/tutorial.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -443,13 +443,13 @@ To support reasoning about code manipulating arrays and computed pointers, CN ha

[source,c]
----
each (i32 i; 0i32 <= i && i < 10i32)
each (u64 i; 0u64 <= i && i < 10u64)
{ Owned<int>(array_shift<int>(p,i)) }
----

In detail, this can be read as follows:

* for each integer `+i+` of CN type `+i32+`, …
* for each integer `+i+` of CN type `+u64+`, …

* if `+i+` is between `+0+` and `+10+`, …

Expand Down Expand Up @@ -508,7 +508,7 @@ Here the CN comment `+/*@ extract Owned<int>, i; @*/+` is a CN "`ghost statement

[source,c]
----
each(i32 j; 0i32 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) }
each(u64 j; 0u64 <= j && j < n) { Owned<int>(array_shift<int>(p,j)) }
----

is split into
Expand All @@ -523,15 +523,15 @@ Owned<int>(array_shift<int>(p,i))
+
[source,c]
----
each(i32 j; 0i32 <= j && j < n && j != i)
each(u64 j; 0u64 <= j && j < n && j != i)
{ Owned<int>(array_shift<int>(p,j)) }
----

After this extraction step, CN can use the (former) extracted resource to justify the access `+p[i]+`.

Following an `+extract+` statement, CN moreover remembers the extracted index and can automatically "`reverse`" the extraction when needed: after type checking the access `+p[i]+` CN must ensure the function’s postcondition holds, which needs the full array ownership again (including the extracted index `+i+`); remembering the index `+i+`, CN then automatically merges resources (1) and (2) again to obtain the required full array ownership, and completes the verification of the function.

So far the specification only guarantees safe execution but does not specify the behaviour of `+read+`. To address this, let’s return to the iterated resources in the function specification. When we specify `+take a1 = each ...+` here, what is `+a1+`? In CN, the output of an iterated resource is a _map_ from indices to resource outputs. In this example, where index `+j+` has CN type `+i32+` and the iterated resource is `+Owned<int>+`, the output `+a1+` is a map from `+i32+` indices to `+i32+` values — CN type `+map<i32,i32>+`. (If the type of `+j+` was `+i64+` and the resource `+Owned<char>+`, `+a1+` would have type `+map<i64,u8>+`.)
So far the specification only guarantees safe execution but does not specify the behaviour of `+read+`. To address this, let’s return to the iterated resources in the function specification. When we specify `+take a1 = each ...+` here, what is `+a1+`? In CN, the output of an iterated resource is a _map_ from indices to resource outputs. In this example, where index `+j+` has CN type `+u64+` and the iterated resource is `+Owned<int>+`, the output `+a1+` is a map from `+u64+` indices to `+i32+` values — CN type `+map<u64,i32>+`.

We can use this to refine our specification with information about the functional behaviour of `+read+`.

Expand All @@ -557,14 +557,14 @@ include_example(exercises/swap_array.c)
////
TODO: BCP: I wrote this, which seemed natural but did not work -- I still don't fully understand why. I think this section will need some more examples / exercises to be fully digestible, or perhaps this is just yet another symptom of my imperfecdt understanding of how the numeric stuff works.

void swap_array (int *p, int n, int i, int j)
/*@ requires take a1 = each(i32 k; 0i32 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
0i32 <= i && i < n;
0i32 <= j && j < n;
void swap_array (int *p, unsigned long n, unsigned long i, unsigned long j)
/*@ requires take a1 = each(u64 k; 0u64 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
0u64 <= i && i < n;
0u64 <= j && j < n;
j != i;
take xi = Owned<unsigned int>(array_shift(p,i));
take xj = Owned<unsigned int>(array_shift(p,j))
ensures take a2 = each(i32 k; 0i32 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
ensures take a2 = each(u64 k; 0u64 <= k && k < n) { Owned<unsigned int>(array_shift<unsigned int>(p,k)) };
a1[i:xj][j:xi] == a2
@*/
{
Expand Down