summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-03 22:44:02 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-03 22:44:02 -0400
commit4030c4239542d1b668c2f328f7142b9796973ddd (patch)
treed46384c848a484a6242de8aa6c346c781505569f
parent39b4b36741bb63fe1bd6da945fc5553ff648d97a (diff)
fixed bug & added while infinite loops (now only they can have ret exprs)
-rw-r--r--allocator.c34
-rw-r--r--arr.c4
-rw-r--r--eval.c9
-rw-r--r--parse.c26
-rw-r--r--test.toc12
-rw-r--r--tests.c25
-rw-r--r--types.c11
-rw-r--r--types.h8
8 files changed, 43 insertions, 86 deletions
diff --git a/allocator.c b/allocator.c
index 6add3cf..4dc05c8 100644
--- a/allocator.c
+++ b/allocator.c
@@ -4,8 +4,6 @@
static void allocr_create(Allocator *a) {
a->first = a->last = NULL;
- a->dyn = NULL;
- a->dyn_len = a->dyn_cap = 0;
}
static void *allocr_malloc(Allocator *a, size_t bytes) {
@@ -39,29 +37,11 @@ static void *allocr_calloc(Allocator *a, size_t n, size_t sz) {
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) {
- DynPage *page = (DynPage *)((char *)data - offsetof(DynPage, data));
- page = err_realloc(page, new_size + sizeof(DynPage));
- *page->self = page;
- return page->data;
- } else {
- if (a->dyn_len >= a->dyn_cap) {
- a->dyn_cap = 2 * (a->dyn_len + 1);
- a->dyn = realloc(a->dyn, a->dyn_cap * sizeof(DynPage *));
- for (size_t i = 0; i < a->dyn_len; i++) {
- a->dyn[i]->self = &a->dyn[i];
- }
- }
- DynPage *page = err_malloc(sizeof(DynPage) + new_size);
- page->self = &a->dyn[a->dyn_len];
- *page->self = page;
- a->dyn_len++;
- return page->data;
- }
- return NULL;
+/* OPTIM */
+static void *allocr_realloc(Allocator *a, void *data, size_t old_size, size_t new_size) {
+ void *ret = allocr_malloc(a, new_size);
+ memcpy(ret, data, old_size);
+ return ret;
}
static void allocr_free_all(Allocator *a) {
@@ -70,8 +50,4 @@ static void allocr_free_all(Allocator *a) {
free(page);
page = next;
}
- for (size_t i = 0; i < a->dyn_len; i++) {
- free(a->dyn[i]);
- }
- free(a->dyn);
}
diff --git a/arr.c b/arr.c
index ea29c8c..7a0ffa9 100644
--- a/arr.c
+++ b/arr.c
@@ -31,14 +31,14 @@ static void arr_resv_(void **arr, size_t n, size_t item_sz) {
}
static void arr_resva_(void **arr, size_t n, size_t item_sz, Allocator *a) {
if (*arr == NULL) {
- ArrHeader *hdr = allocr_realloc(a, NULL, item_sz * n + sizeof(ArrHeader)); /* +1 => prevent ptr overflow */
+ ArrHeader *hdr = allocr_malloc(a, item_sz * n + sizeof(ArrHeader));
hdr->len = 0;
hdr->cap = n;
*arr = hdr->data;
} else {
ArrHeader *hdr = arr_hdr(*arr);
+ hdr = allocr_realloc(a, hdr, item_sz * hdr->cap + sizeof(ArrHeader), item_sz * n + sizeof(ArrHeader));
hdr->cap = n;
- hdr = allocr_realloc(a, hdr, item_sz * n + sizeof(ArrHeader));
if (hdr->len > hdr->cap) hdr->len = hdr->cap;
*arr = hdr->data;
}
diff --git a/eval.c b/eval.c
index cb4f41a..96a7a2c 100644
--- a/eval.c
+++ b/eval.c
@@ -426,11 +426,12 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
case EXPR_WHILE: {
Value cond;
WhileExpr *w = &e->while_;
- bool looped_once = false;
while (1) {
- eval_expr(ev, w->cond, &cond);
- if (!val_truthiness(&cond, &w->cond->type))
- break;
+ if (w->cond) {
+ eval_expr(ev, w->cond, &cond);
+ if (!val_truthiness(&cond, &w->cond->type))
+ break;
+ }
eval_block(ev, &w->body, v);
}
} break;
diff --git a/parse.c b/parse.c
index deda2dd..e79e72d 100644
--- a/parse.c
+++ b/parse.c
@@ -736,17 +736,23 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
e->kind = EXPR_WHILE;
WhileExpr *w = &e->while_;
t->token++;
- Token *cond_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE, NULL);
- if (!cond_end) return false;
- if (!token_is_kw(cond_end, KW_LBRACE)) {
- t->token = cond_end;
- tokr_err(t, "Expected { to open while body.");
- return false;
+ if (token_is_kw(t->token, KW_LBRACE)) {
+ /* infinite loop */
+ w->cond = NULL;
+ } else {
+ Token *cond_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE, NULL);
+ if (!cond_end) return false;
+ if (!token_is_kw(cond_end, KW_LBRACE)) {
+ t->token = cond_end;
+ tokr_err(t, "Expected { to open while body.");
+ return false;
+ }
+ Expression *cond = parser_new_expr(p);
+ w->cond = cond;
+
+ if (!parse_expr(p, cond, cond_end))
+ return false;
}
- Expression *cond = parser_new_expr(p);
- w->cond = cond;
- if (!parse_expr(p, cond, cond_end))
- return false;
if (!parse_block(p, &w->body)) return false;
return true;
}
diff --git a/test.toc b/test.toc
index 09471ae..f8b8059 100644
--- a/test.toc
+++ b/test.toc
@@ -1,15 +1,15 @@
main @= fn() {
- a : [('a' as u8 as f32) / 2 + 0.5 as i8 as &int as u64]int;
+ // a : [('a' as u8 as f32) / 2 + 0.5 as i8 as &int as u64]int;
- foo := fn(x : int) int {
- 7
- };
+ // foo := fn(x : int) int {
+ // 7
+ // };
- bar := foo(3);
+ // bar := foo(3);
a238674 : [if 5 - 5 { 12 } else { 6 }]int;
a2394823 : [{ 3; 7 }]int;
- gfdsdgf : [ while 3 { 5 }]int;
+ gfdsdgf : [ while { 3 } ]int;
// arr1 : ['a' as u8]int;
// arr2 : [main as u64]int;
// arr3 : [main as i64]int;
diff --git a/tests.c b/tests.c
index 8b200d8..e6e5949 100644
--- a/tests.c
+++ b/tests.c
@@ -19,31 +19,6 @@ static void allocr_test(void) {
for (int i = 0; i < nbars; i++)
assert(bars[i] == i);
}
-
- int nfoos1 = 5;
- int *foos = allocr_realloc(&a, NULL, (size_t)nfoos1 * sizeof(int));
- for (int i = 0; i < nfoos1; i++)
- foos[i] = i;
- for (int i = 0; i < nfoos1; i++)
- assert(foos[i] == i);
-
- int nfoos2 = 10;
- foos = allocr_realloc(&a, foos, (size_t)nfoos2 * sizeof(int));
- for (int i = nfoos1; i < nfoos2; i++)
- foos[i] = i;
- for (int i = 0; i < nfoos2; i++)
- assert(foos[i] == i);
-
- int *arr = NULL;
- int n = 1000;
- for (int i = 0; i < n; i++) {
- int *p = arr_adda(&arr, &a);
- *p = i;
- }
- for (int i = 0; i < n; i++) {
- assert(arr[i] == i);
- }
-
allocr_free_all(&a);
}
diff --git a/types.c b/types.c
index f0b3107..2a7fd22 100644
--- a/types.c
+++ b/types.c
@@ -607,12 +607,19 @@ static bool types_expr(Typer *tr, Expression *e) {
case EXPR_WHILE: {
WhileExpr *w = &e->while_;
bool ret = true;
- if (!types_expr(tr, w->cond))
+ if (w->cond && !types_expr(tr, w->cond))
ret = false;
if (!types_block(tr, &w->body))
ret = false;
if (!ret) return false;
- *t = w->body.ret_expr->type;
+ if (w->cond != NULL && w->body.ret_expr != NULL) {
+ err_print(e->where, "A finite loop can't have a return expression (for an infinite loop, use while { ... }).");
+ return false;
+ }
+ if (w->body.ret_expr)
+ *t = w->body.ret_expr->type;
+ else
+ t->kind = TYPE_VOID;
} break;
case EXPR_CALL: {
CallExpr *c = &e->call;
diff --git a/types.h b/types.h
index 64cfaf9..498e7f0 100644
--- a/types.h
+++ b/types.h
@@ -33,17 +33,9 @@ typedef struct Page {
max_align_t data[];
} Page;
-typedef struct DynPage {
- struct DynPage **self;
- max_align_t data[];
-} DynPage;
-
typedef struct {
Page *first;
Page *last;
- DynPage **dyn;
- size_t dyn_len;
- size_t dyn_cap;
} Allocator;
typedef struct {