summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--abbrevs.txt2
-rw-r--r--allocator.c97
-rw-r--r--archive/arr.c61
-rw-r--r--main.c5
-rw-r--r--toc.c1
5 files changed, 166 insertions, 0 deletions
diff --git a/abbrevs.txt b/abbrevs.txt
index cdf5bb1..d5a3a68 100644
--- a/abbrevs.txt
+++ b/abbrevs.txt
@@ -1,9 +1,11 @@
+allocr - allocator
arg - argument
decl - declaration
del - delete
deref - dereference
direct - directive
eof - end of file
+err - error
expr - expression
fn - function
ident - identifier
diff --git a/allocator.c b/allocator.c
new file mode 100644
index 0000000..7d1c6a7
--- /dev/null
+++ b/allocator.c
@@ -0,0 +1,97 @@
+typedef struct Page {
+ struct Page *next;
+ size_t used;
+ max_align_t data[];
+} Page;
+
+typedef struct {
+ Page *first;
+ Page *last;
+} Allocator;
+
+/* number of bytes a page hold, not including the header */
+#define PAGE_SIZE (16384 - sizeof(Page))
+
+static void allocr_create(Allocator *a) {
+ a->first = a->last = NULL;
+}
+
+static void *allocr_malloc(Allocator *a, size_t bytes) {
+ /* position in this page to return */
+ size_t pos = PAGE_SIZE;
+ if (a->last)
+ pos = (a->last->used + sizeof(max_align_t) - 1) / sizeof(max_align_t);
+
+ if (pos * sizeof(max_align_t) + bytes > PAGE_SIZE) {
+ /* make a new page for this data */
+ Page *page = err_malloc(sizeof *page + (bytes > PAGE_SIZE ? bytes : PAGE_SIZE));
+ page->next = NULL;
+ page->used = bytes;
+ if (a->last)
+ a->last->next = page;
+ else
+ a->first = page;
+ a->last = page;
+ return page->data;
+ } else {
+ a->last->used += bytes;
+ return &a->last->data[pos];
+ }
+}
+
+static void *allocr_calloc(Allocator *a, size_t bytes) {
+ void *data = allocr_malloc(a, bytes);
+ memset(data, 0, bytes);
+ return data;
+}
+
+/* IMPORTANT: this can only be called with data which was originally allocated with allocr_realloc(a, NULL, x) */
+static void *allocr_realloc(Allocator *a, void *data, size_t new_size) {
+ if (!data) {
+ Page *page = err_malloc(sizeof *page + new_size);
+ page->used = PAGE_SIZE; /* pretend we used all of this page */
+ page->next = NULL;
+ if (a->last)
+ a->last->next = page;
+ else
+ a->first = page;
+ a->last = page;
+ return page->data;
+ } else {
+ Page *page = (Page *)((char *)data - offsetof(Page, data));
+ page = err_realloc(page, sizeof *page + new_size);
+ return page->data;
+ }
+}
+
+static void allocr_free_all(Allocator *a) {
+ for (Page *page = a->first; page;) {
+ Page *next = page->next;
+ free(page);
+ page = next;
+ }
+}
+
+static void allocr_test(void) {
+ Allocator a;
+ allocr_create(&a);
+ for (int x = 1000; x <= 8000; x += 1000) {
+ size_t nfoos = x;
+ int *foos = allocr_malloc(&a, nfoos * sizeof(int));
+
+ for (size_t i = 0; i < nfoos; i++)
+ foos[i] = (int)i;
+ for (size_t i = 0; i < nfoos; i++)
+ assert(foos[i] == (int)i);
+ size_t nbars = x;
+ int *bars = allocr_calloc(&a, nbars * sizeof(int));
+ for (size_t i = 0; i < nbars; i++)
+ assert(bars[i] == 0);
+ for (size_t i = 0; i < nbars; i++)
+ bars[i] = (int)i;
+ for (size_t i = 0; i < nbars; i++)
+ assert(bars[i] == (int)i);
+ }
+
+ allocr_free_all(&a);
+}
diff --git a/archive/arr.c b/archive/arr.c
new file mode 100644
index 0000000..2555d72
--- /dev/null
+++ b/archive/arr.c
@@ -0,0 +1,61 @@
+typedef struct {
+ void *data;
+ size_t len;
+ size_t cap;
+ size_t item_sz;
+} Array;
+
+static void arr_create(Array *arr, size_t item_sz) {
+ arr->len = arr->cap = 0;
+ arr->item_sz = item_sz;
+ arr->data = NULL;
+}
+
+static inline void arr_reserve(Array *arr, size_t n) {
+ arr->cap = n;
+ arr->data = err_realloc(arr->data, arr->item_sz * arr->cap);
+}
+
+/* like arr_reserve, but sets the length of the array too */
+static inline void arr_set_len(Array *arr, size_t n) {
+ arr->len = arr->cap = n;
+ arr->data = err_realloc(arr->data, arr->item_sz * arr->cap);
+}
+
+static inline void *arr_last(Array *arr) {
+ if (arr->data)
+ return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1));
+ else
+ return NULL;
+}
+
+static void *arr_add(Array *arr) {
+ if (arr->len >= arr->cap) {
+ arr_reserve(arr, (arr->cap + 1) * 2);
+ }
+ arr->len++;
+ return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1));
+}
+
+static void arr_clear(Array *arr) {
+ free(arr->data);
+ arr->len = arr->cap = 0;
+ arr->data = NULL;
+}
+
+static void arr_remove_last(Array *arr) {
+ /* OPTIM (memory): Shorten array. */
+ arr->len--;
+ if (!arr->len) {
+ arr_clear(arr);
+ }
+
+}
+
+static void arr_free(Array *arr) {
+ free(arr->data);
+}
+
+/* NOTE: this will not work if type is a pointer! */
+#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++)
+#define arr_foreach_reverse(arr, type, var) for (type *var = arr_last(arr); var; var == (arr)->data ? var = NULL : var--)
diff --git a/main.c b/main.c
index 596f3de..5c2f1f1 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,8 @@
/*
TODO:
+allocator
+casting errors
+call fns at compile time
finish evaluator
fix void fn type
re-do cgen
@@ -8,6 +11,8 @@ any odd number of "s for a string
#include "toc.c"
int main(int argc, char **argv) {
+ allocr_test();
+ return 0;
if (argc < 2) {
fprintf(stderr, "Please specify an input file.\n");
return EXIT_FAILURE;
diff --git a/toc.c b/toc.c
index 2fd7e86..ac5db05 100644
--- a/toc.c
+++ b/toc.c
@@ -19,6 +19,7 @@ typedef long double Floating; /* OPTIM: Switch to double */
#include "location.c"
#include "err.c"
+#include "allocator.c"
#include "arr.c"
#include "blockarr.c"
#include "str.c"