~lbnz/xr0

850c56fc9735232f3b9de96ce0a38b86b60e6497 — Leibniz Founders 6 months ago 7e47ade feat/symmetric-alloc
chore: remove path logic and sel_absexec for now
M Makefile => Makefile +1 -1
@@ 27,11 27,11 @@ MAIN_OBJ = $(BUILD_DIR)/main.o
VERIFY_OBJ = $(BUILD_DIR)/verify.o

STATE_OBJ = $(BUILD_DIR)/state.o
EXT_OBJ = $(BUILD_DIR)/ext.o
STACK_OBJ = $(BUILD_DIR)/stack.o
HEAP_OBJ = $(BUILD_DIR)/heap.o
LOCATION_OBJ = $(BUILD_DIR)/location.o
BLOCK_OBJ = $(BUILD_DIR)/block.o
EXT_OBJ = $(BUILD_DIR)/ext.o
OBJECT_OBJ = $(BUILD_DIR)/object.o
VALUE_OBJ = $(BUILD_DIR)/value.o
MATH_OBJ = $(BUILD_DIR)/math.o

M src/state/block.c => src/state/block.c +0 -15
@@ 14,7 14,6 @@

struct block {
	struct object_arr *arr;
	bool freed;
};

struct block *


@@ 22,7 21,6 @@ block_create()
{
	struct block *b = malloc(sizeof(struct block));
	b->arr = object_arr_create();
	b->freed = false;
	return b;
}



@@ 38,7 36,6 @@ block_copy(struct block *old)
{
	struct block *new = malloc(sizeof(struct block));
	new->arr = object_arr_copy(old->arr);
	new->freed = old->freed;
	return new;
}



@@ 56,18 53,6 @@ block_str(struct block *block)
	return strbuilder_build(b);
}

bool
block_isfreed(struct block *b)
{
	return b->freed;
}

void
block_free(struct block *b)
{
	b->freed = true;
}

void
block_install(struct block *b, struct object *obj)
{

M src/state/block.h => src/state/block.h +0 -6
@@ 12,12 12,6 @@ block_destroy(struct block *);
char *
block_str(struct block *);

bool
block_isfreed(struct block *);

void
block_free(struct block *);

struct error;
struct value;
struct ast_expr;

M src/state/heap.c => src/state/heap.c +20 -12
@@ 15,6 15,7 @@

struct heap {
	struct block_arr *blocks;
	bool *freed; /* array of same length as blocks */
};

struct heap *


@@ 22,6 23,7 @@ heap_create()
{
	struct heap *h = malloc(sizeof(struct heap)); assert(h);
	h->blocks = block_arr_create();
	h->freed = NULL;
	return h;
}



@@ 29,6 31,7 @@ void
heap_destroy(struct heap *h)
{
	block_arr_destroy(h->blocks);
	free(h->freed);
	free(h);
}



@@ 37,6 40,13 @@ heap_copy(struct heap *h)
{
	struct heap *copy = malloc(sizeof(struct heap));	
	copy->blocks = block_arr_copy(h->blocks);

	int n = block_arr_nblocks(h->blocks);
	bool *freed_copy = malloc(sizeof(bool) * n);
	for (int i = 0; i < n; i++) {
		freed_copy[i] = h->freed[i];	
	}
	copy->freed = freed_copy;
	return copy;
}



@@ 50,7 60,7 @@ heap_str(struct heap *h, char *indent)
	struct block **arr = block_arr_blocks(h->blocks);
	int n = block_arr_nblocks(h->blocks);
	for (int i = 0; i < n; i++) {
		if (block_isfreed(arr[i])) {
		if (h->freed[i]) {
			continue;
		}
		char *block = block_str(arr[i]);


@@ 65,9 75,8 @@ static bool
printdelim(struct heap *h, int start)
{
	int n = block_arr_nblocks(h->blocks);
	struct block **b = block_arr_blocks(h->blocks);
	for (int i = start+1; i < n; i++) {
		if (!block_isfreed(b[i])) {
		if (!h->freed[i]) {
			return true;
		}
	}


@@ 89,7 98,9 @@ heap_newblock(struct heap *h)

	int n = block_arr_nblocks(h->blocks);
	assert(n > 0);

	h->freed = realloc(h->freed, sizeof(bool) * n);
	h->freed[address] = false;
		
	return location_create(
		LOCATION_DYNAMIC, address, ast_expr_constant_create(0)
	);


@@ 101,11 112,10 @@ heap_getblock(struct heap *h, int address)
	if (address >= block_arr_nblocks(h->blocks)) {
		return NULL;
	}
	struct block *b = block_arr_blocks(h->blocks)[address];
	if (block_isfreed(b)) {
	if (h->freed[address]) {
		return NULL;
	}
	return b;
	return block_arr_blocks(h->blocks)[address];
}

struct error *


@@ 113,11 123,10 @@ heap_deallocblock(struct heap *h, int address)
{
	assert(address < block_arr_nblocks(h->blocks));

	struct block *b = block_arr_blocks(h->blocks)[address];
	if (block_isfreed(b)) {
	if (h->freed[address]) {
		return error_create("double free");
	}
	block_free(b);
	h->freed[address] = true;
	return NULL;
}



@@ 128,9 137,8 @@ bool
heap_referenced(struct heap *h, struct state *s)
{
	int n = block_arr_nblocks(h->blocks);
	struct block **b = block_arr_blocks(h->blocks);
	for (int i = 0; i < n; i++) {
		if (!block_isfreed(b[i]) && !block_referenced(s, i)) {
		if (!h->freed[i] && !block_referenced(s, i)) {
			return false;
		}
	}

M src/state/location.c => src/state/location.c +1 -2
@@ 131,8 131,7 @@ location_references(struct location *l1, struct location *l2, struct state *s)
	}

	struct block *b = state_getblock(s, l1);
	assert(b);
	return block_references(b, l2, s);
	return b && block_references(b, l2, s);
}

struct block *

M src/verify/verify.c => src/verify/verify.c +2 -289
@@ 10,56 10,11 @@
#include "value.h"
#include "verify.h"

typedef struct func_arr *Funcarr;

int
func_arr_len(Funcarr);

struct ast_function **
func_arr_paths(Funcarr);

void
func_arr_destroy(Funcarr);

Funcarr
paths_fromfunction(struct ast_function *f);

struct error *
function_verify_paths(Funcarr paths, struct externals *);

struct error *
function_verify(struct ast_function *f, struct externals *ext)
{
	Funcarr paths = paths_fromfunction(f);
	struct error *err = function_verify_paths(paths, ext);
	func_arr_destroy(paths);
	return err;
}

struct error *
path_verify_withstate(struct ast_function *, struct externals *);

struct error *
function_verify_paths(Funcarr paths, struct externals *ext)
{	
	int len = func_arr_len(paths);
	struct ast_function **path = func_arr_paths(paths);
	for (int i = 0; i < len; i++) {
		struct error *err = NULL;
		if ((err = path_verify_withstate(path[i], ext))) {
			return err;
		}
	}
	return NULL;
}

/* path_verify_withstate */

struct error *
path_verify(struct ast_function *f, struct state *state, struct externals *);

struct error *
path_verify_withstate(struct ast_function *f, struct externals *ext)
function_verify(struct ast_function *f, struct externals *ext)
{
	struct state *state = state_create(
		dynamic_str(ast_function_name(f)), ext, ast_function_type(f)


@@ 69,228 24,6 @@ path_verify_withstate(struct ast_function *f, struct externals *ext)
	return err;
}

/* Funcarr */

struct func_arr {
	int n;
	struct ast_function **path;
};

struct func_arr *
func_arr_create()
{
	return calloc(1, sizeof(struct func_arr));
}

int
func_arr_len(struct func_arr *set)
{
	return set->n;
}

struct ast_function **
func_arr_paths(struct func_arr *set)
{
	return set->path;
}

static int
findsel(struct ast_function *);

static void
func_arr_immediate_split_append(struct func_arr *set, struct ast_function *f, int i);

static void
func_arr_append(struct func_arr *set, struct ast_function *f);

struct func_arr *
paths_fromfunction(struct ast_function *f)
{
	assert(!ast_function_isaxiom(f));

	struct func_arr *arr = func_arr_create();

	int sel = findsel(f);
	if (sel != -1) {
		func_arr_immediate_split_append(arr, f, sel);
	} else {
		func_arr_append(arr, f);
	}
	return arr;
}

static int
findsel(struct ast_function *f)
{
	assert(!ast_function_isaxiom(f));

	struct ast_block *body = ast_function_body(f);

	struct ast_stmt **stmt = ast_block_stmts(body);
	int nstmts = ast_block_nstmts(body);

	for (int i = 0; i < nstmts; i++) {
		struct ast_stmt *s = stmt[i];
		if (ast_stmt_kind(s) != STMT_SELECTION) {
			continue;
		}
		assert(!ast_stmt_sel_nest(s)); /* XXX: simple cases first */
		return i;
	}
	return -1;
}

/* func_arr_immediate_split_append */

static struct ast_function *
immediate_split(struct ast_function *f, int i, bool enter);

static void
func_arr_appendrange(struct func_arr *set, struct func_arr *other);

static void
func_arr_immediate_split_append(struct func_arr *set, struct ast_function *f, int i)
{
	struct ast_function *t_path = immediate_split(f, i, true),
			    *f_path = immediate_split(f, i, false);

	struct func_arr *paths_t = paths_fromfunction(t_path),
			*paths_f = paths_fromfunction(f_path);

	func_arr_appendrange(set, paths_t);
	func_arr_appendrange(set, paths_f);

	func_arr_destroy(paths_f);
	func_arr_destroy(paths_t);

	ast_function_destroy(f_path);
	ast_function_destroy(t_path);
}

struct ast_block *
split_block_cond(struct ast_block *b, struct ast_expr *cond, bool enter);

struct ast_block *
split_block_index(struct ast_block *b, int split_index, bool enter);

static struct ast_function *
immediate_split(struct ast_function *f, int split_index, bool enter)
{
	struct ast_block *abs = ast_function_abstract(f),
			 *body = ast_function_body(f);

	struct ast_expr *cond = ast_stmt_sel_cond(ast_block_stmts(body)[split_index]);

	assert(!abs->decl && abs->ndecl == 0);
	return ast_function_create(
		false,
		ast_type_copy(f->ret),
		dynamic_str(f->name),
		f->nparam,
		ast_variables_copy(f->nparam, f->param),
		split_block_cond(abs, cond, enter),
		split_block_index(body, split_index, enter)
	);
}

/* split_block_cond */

struct ast_stmt *
choose_split_path(struct ast_stmt *old_stmt, bool should_split, bool enter);

struct ast_block *
split_block_cond(struct ast_block *b, struct ast_expr *cond, bool enter)
{
	int nstmts = ast_block_nstmts(b);
	struct ast_stmt **old_stmt = ast_block_stmts(b);

	int n = 0;
	struct ast_stmt **stmt = NULL;
	for (int i = 0; i < nstmts; i++) {
		struct ast_stmt *old_s = old_stmt[i];
		bool should_split = 
			ast_stmt_kind(old_s) == STMT_SELECTION &&
			ast_expr_equal(ast_stmt_sel_cond(old_s), cond);
		struct ast_stmt *s = choose_split_path(
			old_s, should_split, enter
		);
		if (!s) {
			continue;
		}
		stmt = realloc(stmt, sizeof(struct ast_stmt *) * ++n);
		stmt[n-1] = ast_stmt_copy(s);
	}
	struct ast_variable **decl = b->decl
		? ast_variables_copy(b->ndecl, b->decl)
		: NULL;
	return ast_block_create(
		decl, b->ndecl,
		stmt, n
	);
}

struct ast_stmt *
choose_split_path(struct ast_stmt *stmt, bool should_split, bool enter)
{
	if (should_split) {
		return enter ? ast_stmt_sel_body(stmt) : NULL;
	}
	return stmt;
}

struct ast_block *
split_block_index(struct ast_block *b, int split_index, bool enter)
{
	int nstmts = ast_block_nstmts(b);
	struct ast_stmt **old_stmt = ast_block_stmts(b);

	int n = 0;
	struct ast_stmt **stmt = NULL;
	for (int i = 0; i < nstmts; i++) {
		struct ast_stmt *s = choose_split_path(
			old_stmt[i], i == split_index, enter
		);
		if (!s) {
			continue;
		}
		stmt = realloc(stmt, sizeof(struct ast_stmt *) * ++n);
		stmt[n-1] = ast_stmt_copy(s);
	}
	struct ast_variable **decl = b->decl
		? ast_variables_copy(b->ndecl, b->decl)
		: NULL;
	return ast_block_create(
		decl, b->ndecl,
		stmt, n
	);
}

static void
func_arr_appendrange(struct func_arr *arr, struct func_arr *range)
{
	for (int i = 0; i < range->n; i++) {
		func_arr_append(arr, range->path[i]);
	}
}

static void
func_arr_append(struct func_arr *arr, struct ast_function *f)
{
	arr->path = realloc(arr->path,
		sizeof(struct ast_function *) * ++arr->n);
	arr->path[arr->n-1] = ast_function_copy(f);
}

void
func_arr_destroy(struct func_arr *arr)
{
	for (int i = 0; i < arr->n; i++) {
		ast_function_destroy(arr->path[i]);
	}
	free(arr->path);
	free(arr);
}

/* path_verify */

static struct error *


@@ 1155,7 888,6 @@ prepare_parameters(struct ast_function *f, struct result_arr *args,

		struct result res = args->res[i];
		if (result_iserror(res)) {
			printf("state: %s\n", state_str(state));
			struct strbuilder *b = strbuilder_create();
			strbuilder_printf(
				b, "param `%s': ",


@@ 1511,10 1243,10 @@ abstract_audit(struct ast_function *f, struct state *actual_state,
{
	struct error *err = NULL;

	/*printf("actual: %s\n", state_str(actual_state));*/
	if (!state_hasgarbage(actual_state)) {
		return error_create("garbage on heap");
	}
	/*printf("actual: %s\n", state_str(actual_state));*/

	struct state *alleged_state = state_create(
		dynamic_str(ast_function_name(f)), ext, ast_function_type(f)


@@ 1597,9 1329,6 @@ static struct result
expr_absexec(struct ast_expr *expr, struct state *state);

static struct result
sel_absexec(struct ast_stmt *stmt, struct state *state);

static struct result
iter_absexec(struct ast_stmt *stmt, struct state *state);

static struct result


@@ 1614,8 1343,6 @@ stmt_absexec(struct ast_stmt *stmt, struct state *state)
		return result_value_create(NULL);
	case STMT_EXPR:
		return expr_absexec(ast_stmt_as_expr(stmt), state);
	case STMT_SELECTION:
		return sel_absexec(stmt, state);
	case STMT_ITERATION:
		return iter_absexec(stmt, state);
	case STMT_COMPOUND:


@@ 1714,20 1441,6 @@ assign_absexec(struct ast_expr *expr, struct state *state)
}

static struct result
sel_absexec(struct ast_stmt *stmt, struct state *state)
{
	struct ast_expr *cond = ast_stmt_sel_cond(stmt);
	if (!expr_decide(cond, state)) {
		struct ast_stmt *nest = ast_stmt_sel_nest(stmt);
		if (nest) {
			return stmt_absexec(nest, state);
		} 
		return result_value_create(NULL);
	}
	return stmt_absexec(ast_stmt_sel_body(stmt), state);
}

static struct result
iter_absexec(struct ast_stmt *stmt, struct state *state)
{
	struct error *err;

M tests/0-basic/200-free-param.x => tests/0-basic/200-free-param.x +5 -2
@@ 1,7 1,10 @@
#include <stdlib.h>

void
unit(void *p) [ .dealloc p; ]
{
unit(void *p) [
	pre: p = malloc($);

	.dealloc p;
]{
	free(p);
}

M tests/3-program/matrix.x => tests/3-program/matrix.x +4 -2
@@ 59,8 59,10 @@ struct matrix *
matrix_add(struct matrix *m1, struct matrix *m2) [
	int i;

	pre: m1 = matrix_create($, $);
	pre: m2 = matrix_create($, $);
	pre: {
		m1 = matrix_create($, $);
		m2 = matrix_create($, $);
	}

	.alloc result;
	.alloc result->data;