~lbnz/xr0

0f07753c18ce3ac46520ae22fc70127372fb6a32 — Claude Betz 6 months ago b209eef feat/program-1-topological-sort
checkpoint testing
M Makefile => Makefile +3 -2
@@ 66,7 66,7 @@ $(XR0V): $(MAIN_OBJ) $(BIN_DIR)
	@$(CC) $(CFLAGS) -o $@ $(MAIN_OBJ) $(OBJECTS)

lex: $(XR0V)
	$(VALGRIND) $(XR0V) -I libx tests/3-program/100-lex/parse.x
	$(XR0V) -I libx tests/3-program/100-lex/parse.x

lex-leaks: $(XR0V)
	$(VALGRIND) --leak-check=full \


@@ 123,7 123,8 @@ $(LOCATION_OBJ): $(STATE_DIR)/location.c $(UTIL_OBJ)
	@printf 'CC\t$@\n'
	@$(CC) $(CFLAGS) -o $@ -c $(STATE_DIR)/location.c

$(UTIL_OBJ): $(UTIL_DIR)/util.c $(BUILD_DIR)

$(UTIL_OBJ): $(UTIL_DIR)/util.c $(BUILD_DIR) 
	@printf 'CC\t$@\n'
	@$(CC) $(CFLAGS) -o $@ -c $(UTIL_DIR)/util.c


M include/ast.h => include/ast.h +6 -0
@@ 163,6 163,9 @@ ast_expr_eval(struct ast_expr *, struct state *);
struct result *
ast_expr_absexec(struct ast_expr *, struct state *);

struct string_arr *
ast_expr_getfuncs(struct ast_expr *);

struct ast_stmt;

struct ast_block;


@@ 552,4 555,7 @@ ast_append(struct ast *, struct ast_externdecl *);
void
ast_destroy(struct ast *);

struct string_arr *
ast_stmt_getfuncs(struct ast_stmt *);

#endif

M include/util.h => include/util.h +33 -0
@@ 67,4 67,37 @@ error_create(char *s);
struct error *
error_prepend(struct error *, char *msg);

/* XXX: string_arr: to be macro */

struct string_arr {
	int n;
	char **s;
};

struct string_arr *
string_arr_create();

void
string_arr_destroy();

char **
string_arr_s(struct string_arr *);

int
string_arr_n(struct string_arr *);

int
string_arr_append(struct string_arr *, char *);

char *
string_arr_deque(struct string_arr *);

char *
string_arr_str(struct string_arr *);

struct externals;

char *
topological_order(char *func_name, struct externals *);

#endif

M main.c => main.c +16 -58
@@ 20,23 20,6 @@

int yyparse();

struct string_arr;

struct string_arr *
string_arr_create();

void
string_arr_destroy(struct string_arr *);

void
string_arr_append(struct string_arr *, char *);

char **
string_arr_s(struct string_arr *);

int
string_arr_n(struct string_arr *);

struct config {
	char *infile;
	char *outfile;


@@ 79,46 62,6 @@ parse_config(int argc, char *argv[])
	};
}

struct string_arr {
	int n;
	char **s;
};

struct string_arr *
string_arr_create()
{
	return calloc(1, sizeof(struct string_arr));
}

void
string_arr_destroy(struct string_arr *arr)
{
	for (int i = 0; i < arr->n; i++) {
		free(arr->s[i]);
	}
	free(arr);
}

void
string_arr_append(struct string_arr *arr, char *s)
{
	arr->s = realloc(arr->s, sizeof(char *) * ++arr->n);
	arr->s[arr->n-1] = s;
}

char **
string_arr_s(struct string_arr *arr)
{
	return arr->s;
}

int
string_arr_n(struct string_arr *arr)
{
	return arr->n;
}


char *
genincludes(struct string_arr *includedirs)
{


@@ 187,7 130,6 @@ should_verify(struct ast_externdecl *decl)
void
pass1(struct ast *root, struct externals *ext)
{
	struct error *err;
	/* TODO:
	 * - enforce syntax rules
	 * - check that sfuncs have no bodies


@@ 198,6 140,15 @@ pass1(struct ast *root, struct externals *ext)
	for (int i = 0; i < root->n; i++) {
		struct ast_externdecl *decl = root->decl[i];
		ast_externdecl_install(decl, ext);
	}
}

void
pass_verify(struct ast *root, struct externals *ext)
{
	struct error *err;
	for (int i = 0; i < root->n; i++) {
		struct ast_externdecl *decl = root->decl[i];
		if (!should_verify(decl)) {
			continue;
		}


@@ 209,6 160,7 @@ pass1(struct ast *root, struct externals *ext)
			exit(EXIT_FAILURE);
		}
	}

}

int


@@ 228,7 180,13 @@ main(int argc, char *argv[])

	/* TODO: move table from lexer to pass1 */
	struct externals *ext = externals_create();

	pass1(root, ext);
	
	/* XXX: optionally do topological order based on flag */
	topological_order("main", ext);

	pass_verify(root, ext);
	externals_destroy(ext);

	ast_destroy(root);

M src/ast/expr/expr.c => src/ast/expr/expr.c +6 -0
@@ 806,4 806,10 @@ binary_e2(struct ast_expr *e2, enum ast_binary_operator op)
	}
}

struct string_arr *
ast_expr_getfuncs(struct ast_expr *expr)
{
	assert(false);
}

#include "verify.c"

M src/ast/expr/expr.h => src/ast/expr/expr.h +3 -0
@@ 67,4 67,7 @@ struct ast_expr *
ast_expr_binary_create(struct ast_expr *e1, enum ast_binary_operator,
		struct ast_expr *e2);

struct string_arr *
ast_expr_getfuncs(struct ast_expr *);

#endif

M src/ast/stmt/stmt.c => src/ast/stmt/stmt.c +53 -0
@@ 642,4 642,57 @@ ast_stmt_as_expr(struct ast_stmt *stmt)
	return stmt->u.expr;
}

static struct string_arr *
ast_stmt_expr_getfuncs(struct ast_stmt *stmt);

static struct string_arr *
ast_stmt_selection_getfuncs(struct ast_stmt *stmt);

static struct string_arr *
ast_stmt_iteration_getfuncs(struct ast_stmt *stmt);

static struct string_arr *
ast_stmt_compound_getfuncs(struct ast_stmt *stmt);

struct string_arr *
ast_stmt_getfuncs(struct ast_stmt *stmt)
{
	switch (stmt->kind) {
	case STMT_EXPR:
		return ast_stmt_expr_getfuncs(stmt);
	case STMT_SELECTION:
		return ast_stmt_selection_getfuncs(stmt);
	case STMT_ITERATION:
		return ast_stmt_iteration_getfuncs(stmt);
	case STMT_COMPOUND:
		return ast_stmt_compound_getfuncs(stmt);
	default:
		assert(false);
	}
}

static struct string_arr *
ast_stmt_expr_getfuncs(struct ast_stmt *stmt)
{
	return ast_expr_getfuncs(stmt->u.expr);
}

static struct string_arr *
ast_stmt_selection_getfuncs(struct ast_stmt *stmt)
{
	assert(false);		
}

static struct string_arr *
ast_stmt_iteration_getfuncs(struct ast_stmt *stmt)
{
	assert(false);
}

static struct string_arr *
ast_stmt_compound_getfuncs(struct ast_stmt *stmt)
{
	assert(false);
}

#include "verify.c"

M src/ast/stmt/stmt.h => src/ast/stmt/stmt.h +5 -0
@@ 1,6 1,8 @@
#ifndef XR0_AST_STMT_H
#define XR0_AST_STMT_H

#include "util.h"

enum ast_stmt_kind {
	STMT_NOP		= 1 << 0,
	STMT_LABELLED		= 1 << 1,


@@ 17,4 19,7 @@ enum ast_stmt_kind {
enum ast_stmt_kind
ast_stmt_kind(struct ast_stmt *);

struct string_arr *
ast_stmt_getfuncs(struct ast_stmt *stmt);

#endif

M src/ext/ext.c => src/ext/ext.c +1 -1
@@ 1,4 1,5 @@
#include <stdlib.h>
#include <assert.h>
#include "ast.h"
#include "util.h"



@@ 69,4 70,3 @@ externals_gettype(struct externals *ext, char *id)
{
	return map_get(ext->type, id);
}


M src/util/util.c => src/util/util.c +278 -0
@@ 3,7 3,9 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "ast.h"
#include "util.h"
#include "ext.h"

char *
dynamic_str(const char *s)


@@ 200,6 202,282 @@ error_prepend(struct error* e, char *prefix)
	return error_create(new_msg);
}

/* string_arr */

struct string_arr *
string_arr_create()
{
	struct string_arr *arr = calloc(1, sizeof(struct string_arr));
	assert(arr);
	return arr;
}

void
string_arr_destroy(struct string_arr *arr)
{
	for (int i = 0; i < arr->n; i++) {
		free(arr->s[i]);
	}
	free(arr->s);
	free(arr);
}

char **
string_arr_s(struct string_arr *arr)
{
	return arr->s;
}

int
string_arr_n(struct string_arr *arr)
{
	return arr->n;
}

/* string_arr_append: Append struct node to array and return index (address). */
int
string_arr_append(struct string_arr *arr, char *s)
{
	arr->s = realloc(arr->s, sizeof(struct string_arr) * ++arr->n);
	assert(arr->s);
	int loc = arr->n-1;
	arr->s[loc] = s;
	return loc;
}

struct string_arr *
string_arr_copy(struct string_arr *old)
{
	struct string_arr *new = string_arr_create();
	for (int i = 0; i < old->n; i++) {
		string_arr_append(new, dynamic_str(old->s[i]));
	}
	return new;
}

char *
string_arr_deque(struct string_arr *arr)
{
	char *ret = dynamic_str(arr->s[arr->n-1]);
	free(arr->s[arr->n-1]);
	struct string_arr *new = realloc(arr, sizeof(struct string_arr) * arr->n-1);
	assert(new);
	return ret;
}

char *
string_arr_str(struct string_arr *string_arr)
{
	struct strbuilder *b = strbuilder_create();
	char **s = string_arr->s;
	int n = string_arr->n;
	for (int i = 0; i < n; i++) {
		char *str = s[i];
		strbuilder_printf(b, "%s%s", str, (i + 1 < n) ? ", " : "");
		free(s);
	}
	return strbuilder_build(b);
}

/*
 * map<node, string_arr> g maps node to adjacent neighbouring nodes
 */

static struct map *
build_funcgraph(char *fname, struct externals *ext);

static struct map *
build_testfuncgraph();

static struct map *
calculate_indegrees(struct map *g);

static struct string_arr *
build_indegree_zero(struct map *indegrees);

char *
topological_order(char *fname, struct externals *ext)
{
	/* struct map *g = build_funcgraph(fname, ext); */
	struct map *g = build_testfuncgraph();
	struct map *indegrees = calculate_indegrees(g);
	struct string_arr *indegree_zero = build_indegree_zero(indegrees);

	struct string_arr *ordered = string_arr_create();
	/* while there are nodes of indegree zero */
	while (indegree_zero->n > 0) {
		/* add one node with indegree zero to ordered */
		char *curr = string_arr_deque(indegree_zero);
		string_arr_append(ordered, curr);

		/* decrement indegree of that nodes neighbours */
		struct string_arr *neighbours = (struct string_arr *) map_get(g, curr);
		for (int i = 0; i < neighbours->n; i++) {
			char *node = neighbours->s[i];
			int *count = (int *) map_get(indegrees, node);
			if (*count == 0) {
				string_arr_append(indegree_zero, dynamic_str(node));
			}
			*count = *count - 1;
		}
	}

	/* no more nodes with incoming edges */
	if (ordered->n != g->n) {
		assert(false); /* ERROR: cycle */
	}

	printf("order: %s\n", string_arr_str(ordered));
	assert(false);
	return NULL;
}

static struct map *
build_testfuncgraph()
{
	struct map *g = map_create();

	struct string_arr *main_deps = string_arr_create();
	string_arr_append(main_deps, dynamic_str("read_file"));
	string_arr_append(main_deps, dynamic_str("parse"));
	string_arr_append(main_deps, dynamic_str("lexer_print"));
	string_arr_append(main_deps, dynamic_str("lexer_destroy"));

	struct string_arr *read_file_deps = string_arr_create();
	string_arr_append(read_file_deps, dynamic_str("fopen"));
	string_arr_append(read_file_deps, dynamic_str("fseek"));
	string_arr_append(read_file_deps, dynamic_str("malloc"));
	string_arr_append(read_file_deps, dynamic_str("fread"));
	string_arr_append(read_file_deps, dynamic_str("fclose"));

	struct string_arr *parse_deps = string_arr_create();
	string_arr_append(parse_deps, dynamic_str("parse_defs"));
	string_arr_append(parse_deps, dynamic_str("strcmp"));
	string_arr_append(parse_deps, dynamic_str("parse_rules"));
	string_arr_append(parse_deps, dynamic_str("parse_toeof"));

	string_arr_append(parse_deps, dynamic_str("skipws"));
	string_arr_append(parse_deps, dynamic_str("fprintf"));
	string_arr_append(parse_deps, dynamic_str("exit"));

	struct string_arr *parse_defs_deps = string_arr_create();
	string_arr_append(parse_defs_deps, dynamic_str("parse_defsrow"));
	string_arr_append(parse_defs_deps, dynamic_str("skipoptions"));
	string_arr_append(parse_defs_deps, dynamic_str("parse_defsproper"));

	string_arr_append(parse_defs_deps, dynamic_str("skipws"));
	string_arr_append(parse_defs_deps, dynamic_str("fprintf"));
	string_arr_append(parse_defs_deps, dynamic_str("exit"));
	
	map_set(g, dynamic_str("main"), main_deps);

	map_set(g, dynamic_str("read_file"), read_file_deps);

	map_set(g, dynamic_str("fopen"), string_arr_create());
	map_set(g, dynamic_str("fseek"), string_arr_create());
	map_set(g, dynamic_str("malloc"), string_arr_create());
	map_set(g, dynamic_str("fread"), string_arr_create());
	map_set(g, dynamic_str("fclose"), string_arr_create());

	map_set(g, dynamic_str("parse"), parse_deps);

	map_set(g, dynamic_str("parse_defs"), parse_defs_deps);

	map_set(g, dynamic_str("parse_defsrow"), string_arr_create());
	map_set(g, dynamic_str("skipoptions"), string_arr_create());
	map_set(g, dynamic_str("parse_defsproper"), string_arr_create());

	map_set(g, dynamic_str("skipws"), string_arr_create());
	map_set(g, dynamic_str("fprintf"), string_arr_create());
	map_set(g, dynamic_str("exit"), string_arr_create());

	map_set(g, dynamic_str("strncmp"), string_arr_create());
	map_set(g, dynamic_str("parse_rules"), string_arr_create());
	map_set(g, dynamic_str("parse_toeof"), string_arr_create());
	map_set(g, dynamic_str("lexer_create"), string_arr_create());

	map_set(g, dynamic_str("lexer_print"), string_arr_create());

	map_set(g, dynamic_str("lexer_destroy"), string_arr_create());

	map_set(g, dynamic_str("free"), string_arr_create());

	return g;
}

static void
recurse_funcgraph(struct map *m, char *name, struct externals *ext);

struct map *
build_funcgraph(char *fname, struct externals *ext)
{
	struct map *g = map_create();

	recurse_funcgraph(g, fname, ext);

	return g;
}

static void
recurse_funcgraph(struct map *g, char *fname, struct externals *ext)
{
	struct ast_function *f = externals_getfunc(ext, fname);
	struct ast_block *body = ast_function_body(f);
	int nstmts = ast_block_nstmts(body);
	struct ast_stmt **stmt = ast_block_stmts(body);

	struct string_arr *val = string_arr_create();
	for (int i = 0; i < nstmts; i++) {
		struct string_arr *farr = ast_stmt_getfuncs(stmt[i]);		
		if (!farr) {
			continue;
		}

		char **func = string_arr_s(farr); 
		for (int j = 0; j < string_arr_n(farr); j++) {
			/* XXX: avoid duplicates, check for/ use set */
			string_arr_append(val, func[i]);	

			/* recursively build for other funcs */
			recurse_funcgraph(g, func[i], ext);
		}
	}

	map_set(g, dynamic_str(fname), val);
}

static struct map *
calculate_indegrees(struct map *g)
{
	struct map *indegrees = map_create();
	for (int i = 0; i < g->n; i++) {
		struct entry e = g->entry[i];
		map_set(indegrees, dynamic_str(e.key), 0);	
	}

	for (int i = 0; i < g->n; i++) {
		struct entry e = g->entry[i];
		struct string_arr *n_arr = map_get(g, e.key);
		for (int j = 0; j < n_arr->n; j++) {
			int *count = (int *) map_get(indegrees, e.key);
			*count = *count + 1; /* XXX */
		}
	}
	return indegrees;
}

static struct string_arr *
build_indegree_zero(struct map *indegrees)
{
	struct string_arr *indegree_zero = string_arr_create();
	for (int i = 0; i < indegrees->n; i++) {
		struct entry e = indegrees->entry[i];
		if (map_get(indegrees, e.key) == 0) {
			string_arr_append(
				indegree_zero,
				dynamic_str((char *) e.value)
			);
		}
	}
	return indegree_zero;
}