249 lines
3.9 KiB
C
249 lines
3.9 KiB
C
/*
|
|
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
/*
|
|
* Type strengthen test cases.
|
|
*/
|
|
|
|
struct ure {
|
|
int x;
|
|
struct ure *n;
|
|
};
|
|
|
|
|
|
/*********************
|
|
* Pure functions.
|
|
*********************/
|
|
void pure_f(void)
|
|
{
|
|
}
|
|
|
|
void pure_f2(void)
|
|
{
|
|
pure_f();
|
|
}
|
|
|
|
struct ure *pure_g(struct ure *p)
|
|
{
|
|
return p;
|
|
}
|
|
|
|
int pure_h(struct ure *p)
|
|
{
|
|
return !!p;
|
|
}
|
|
|
|
int pure_i(int x)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
int pure_j(struct ure s)
|
|
{
|
|
return s.x;
|
|
}
|
|
|
|
int pure_k(struct ure s)
|
|
{
|
|
return pure_i(s.x) && pure_j(s);
|
|
}
|
|
|
|
/* NB: L2Opt removes the division guard, so this lifts successfully. */
|
|
unsigned pure_div_roundup(unsigned x, unsigned n)
|
|
{
|
|
/* Quiz: is this function correct? */
|
|
if (n == 0) {
|
|
return 0;
|
|
}
|
|
return (x + (n - 1)) / n;
|
|
}
|
|
|
|
|
|
|
|
/*********************
|
|
* Read-only state monad.
|
|
*********************/
|
|
unsigned gets_x;
|
|
unsigned gets_y[4];
|
|
|
|
/*
|
|
Force the globals to be translated as variables.
|
|
Otherwise, c-parser turns them into constants because nothing
|
|
writes to them.
|
|
|
|
We could turn on globals_all_addressed in c-parser,
|
|
but that causes the globals to become generic pointers,
|
|
and autocorres loses the knowledge that those pointers
|
|
always point to valid objects.
|
|
|
|
Basically, the read-only monad is kind of flimsy and of
|
|
dubious usefulness. But see type_strengthen_tricks.thy.
|
|
*/
|
|
void hax(void)
|
|
{
|
|
gets_x = 42;
|
|
gets_y[0] = 42;
|
|
}
|
|
|
|
unsigned gets_f(void)
|
|
{
|
|
return gets_x;
|
|
}
|
|
|
|
unsigned gets_g(void)
|
|
{
|
|
unsigned y[4] = {0};
|
|
y[0] = gets_y[0];
|
|
y[1] = gets_y[1];
|
|
y[2] = gets_y[2];
|
|
y[3] = gets_y[3];
|
|
if (y[0] && y[1] && y[2] && y[3]) {
|
|
if (y[0]) {
|
|
y[0] += y[1];
|
|
}
|
|
if (y[1]) {
|
|
y[1] += y[2];
|
|
}
|
|
if (y[2]) {
|
|
y[2] += y[3];
|
|
}
|
|
if (y[3]) {
|
|
y[3] += y[0];
|
|
}
|
|
} else {
|
|
y[0] = 1;
|
|
y[1] += y[0];
|
|
y[2] += y[1];
|
|
y[3] += y[2];
|
|
}
|
|
return y[0] * y[1] * y[2] * y[3];
|
|
}
|
|
|
|
|
|
|
|
/*********************
|
|
* Option monad (Read with failure).
|
|
*********************/
|
|
unsigned opt_f(unsigned *p)
|
|
{
|
|
return *p;
|
|
}
|
|
|
|
int opt_g(int n)
|
|
{
|
|
return n + 1;
|
|
}
|
|
|
|
unsigned opt_h(struct ure *s)
|
|
{
|
|
if (!s) {
|
|
return 0;
|
|
}
|
|
return 1 + opt_h(s->n);
|
|
}
|
|
|
|
int opt_none(void);
|
|
int opt_i(void)
|
|
{
|
|
return opt_none();
|
|
}
|
|
|
|
int opt_j(struct ure *p, struct ure *l)
|
|
{
|
|
return p->x <= l->x;
|
|
}
|
|
|
|
/* This doesn't read state at all, but AutoCorres assumes loops may fail (to terminate). */
|
|
unsigned opt_l(unsigned n)
|
|
{
|
|
unsigned p = 0;
|
|
while (n > 1) {
|
|
p++;
|
|
n /= 10;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/* Ditto for recursion. */
|
|
unsigned opt_a(unsigned m, unsigned n)
|
|
{
|
|
if (m == 0) {
|
|
return n + 1;
|
|
}
|
|
if (n == 0) {
|
|
return opt_a(m - 1, 1);
|
|
}
|
|
return opt_a(m - 1, opt_a(m, n - 1));
|
|
}
|
|
|
|
/* Test for measure_call */
|
|
unsigned opt_a2(unsigned n)
|
|
{
|
|
return opt_a(n, n);
|
|
}
|
|
|
|
|
|
/*********************
|
|
* State monad (with failure).
|
|
* TODO: state monad is no longer used, rename these examples.
|
|
*********************/
|
|
void st_f(struct ure *p, struct ure *s)
|
|
{
|
|
p->n = s;
|
|
}
|
|
|
|
unsigned st_g(unsigned *p)
|
|
{
|
|
*p = 42;
|
|
return *p;
|
|
}
|
|
|
|
unsigned st_h(unsigned p)
|
|
{
|
|
return st_g((unsigned *)p);
|
|
}
|
|
|
|
struct ure *st_i(struct ure *p, struct ure *l)
|
|
{
|
|
if (opt_j(p, l) || !l) {
|
|
if (l) {
|
|
p->n = l->n;
|
|
}
|
|
return p;
|
|
} else {
|
|
l->n = st_i(p, l->n);
|
|
return l;
|
|
}
|
|
}
|
|
|
|
/*********************
|
|
* Exception monad, the most general monad.
|
|
*********************/
|
|
int exc_f(char *s, int *n)
|
|
{
|
|
int x = 0;
|
|
int sg = 1;
|
|
if (*s == '-') {
|
|
sg = -1;
|
|
s++;
|
|
} else if (*s == '+') {
|
|
s++;
|
|
}
|
|
for (; *s; s++) {
|
|
if (*s >= '0' && *s <= '9') {
|
|
x = 10 * x + sg * (*s - '0');
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
if (*s) {
|
|
return -1;
|
|
} else {
|
|
*n = x;
|
|
return 0;
|
|
}
|
|
}
|