#include #include #include $input int K; // growing step $assume(K > 0); int N; // initial length of the array, havoced at main int * a; // pointer to the arbitrary array of length N int l, r; // l and r, havoed at main void left() { if (l != 0) { l--; r--; a[r] = a[l]; } } void right() { if (r < N) { a[l] = a[r]; r++; l++; } } void delete() { if (l > 0) { l--; } } void grow() { int * b = (int *)malloc(sizeof(int) * (N + K)); memcpy(b, a, sizeof(int) * l); memcpy(b+r+K, a+r, sizeof(int) * (N-r)); r += K; N += K; free(a); a = b; } void insert(int x) { if (l == r) grow(); a[l] = x; l++; } /* ********************** Drivers ******************** */ void left_driver() { $assume_push(l <= r && 0 <= l && r < N); int pre_text[N-r+l]; // the text content at pre-state a = (int *)malloc(sizeof(int) * N); memcpy(pre_text, a, l * sizeof(int)); memcpy(pre_text+l, a+r, (N-r) * sizeof(int)); // call left: left(); int text[N-r+l]; // the text content at post-state memcpy(text, a, l * sizeof(int)); memcpy(text+l, a+r, (N-r) * sizeof(int)); // text content preserves: $assert_equals(&text, &pre_text); free(a); $assume_pop(); } void right_driver() { // assumptions and assertions are identical to left_driver. $assume_push(l <= r && 0 <= l && r < N); int pre_text[N-r+l]; a = (int *)malloc(sizeof(int) * N); memcpy(pre_text, a, l * sizeof(int)); memcpy(pre_text+l, a+r, (N-r) * sizeof(int)); // call right: right(); int text[N-r+l]; memcpy(text, a, l * sizeof(int)); memcpy(text+l, a+r, (N-r) * sizeof(int)); $assert_equals(&text, &pre_text); free(a); $assume_pop(); } void delete_driver() { $assume_push(l <= r && 0 <= l && r < N); int pre_text[N-r+l]; // the text content at pre-state int pre_l = l; // value of l at pre-state a = (int *)malloc(sizeof(int) * N); memcpy(pre_text, a, l * sizeof(int)); memcpy(pre_text+l, a+r, (N-r) * sizeof(int)); // call delete: delete(); int text[N-r+l]; // the text content at post-state int numDel = pre_l - l; // the number of deleted element, either 1 or 0 memcpy(text, a, l * sizeof(int)); memcpy(text+l, a+r, (N-r) * sizeof(int)); // text content before l - 1 preserves: $assert($forall (int i : 0 .. l-2) pre_text[i] == text[i]); // text content after l - 1 preserves but shift to left by numDel: $assert($forall (int i : l .. (N-r+l-1)) pre_text[i+numDel] == text[i]); free(a); $assume_pop(); } void insert_driver() { $assume_push(l <= r && 0 <= l && r < N); int pre_text[N-r+l]; // the text content at pre-state int x; // the arbitrary inserted value a = (int *)malloc(sizeof(int) * N); $havoc(&x); memcpy(pre_text, a, l * sizeof(int)); memcpy(pre_text+l, a+r, (N-r) * sizeof(int)); // call delete: insert(x); int text[N-r+l]; // the text content at post-state memcpy(text, a, l * sizeof(int)); memcpy(text+l, a+r, (N-r) * sizeof(int)); // The text content before l-1 preserves: $assert($forall (int i : 0 .. l-2) pre_text[i] == text[i]); // The element at l-1 is the inserted one: $assert(text[l-1] == x); // The text content after l-1 preserves but shift to right by one: $assert($forall (int i : l .. (N-r+l-1)) pre_text[i-1] == text[i]); free(a); $assume_pop(); } void grow_driver() { $assume_push(l <= r && 0 <= l && r < N); int pre_text[N-r+l]; // the text content at pre-state a = (int *)malloc(sizeof(int) * N); memcpy(pre_text, a, l * sizeof(int)); memcpy(pre_text+l, a+r, (N-r) * sizeof(int)); // call grow: grow(); int text[N-r+l]; // the text content at post-state memcpy(text, a, l * sizeof(int)); memcpy(text+l, a+r, (N-r) * sizeof(int)); // the text content is preserved: $assert_equals(&text, &pre_text); free(a); $assume_pop(); } /* **************** Main: the Entry ************** */ int main() { $havoc(&N); $assume(N > 0); $havoc(&l); $havoc(&r); left_driver(); right_driver(); delete_driver(); grow_driver(); insert_driver(); return 0; }