diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-21 11:09:07 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-21 11:09:07 -0400 |
commit | 9d1960f4cd0e1a78abfecce4d5bfa4d850955852 (patch) | |
tree | 89622e6011aee006e017537d2251be21f8d71f37 | |
parent | 965d5dee1fe6cd28ad92d7f5007c90b6d7d2ff58 (diff) |
compile time recursion
-rw-r--r-- | arr.c | 6 | ||||
-rw-r--r-- | cgen.c | 7 | ||||
-rw-r--r-- | decls_cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 21 | ||||
-rw-r--r-- | main.c | 6 | ||||
-rw-r--r-- | out.c | 30 | ||||
-rw-r--r-- | scope.c | 16 | ||||
-rw-r--r-- | test.toc | 36 | ||||
-rw-r--r-- | types.c | 6 |
9 files changed, 50 insertions, 80 deletions
@@ -62,7 +62,7 @@ static void *arr_add_(void **arr, size_t item_sz) { } else { hdr = arr_hdr(*arr); if (hdr->len >= hdr->cap) { - arr_resv_(arr, hdr->len * 2, item_sz); + arr_resv_(arr, hdr->len * 2 + 1, item_sz); hdr = arr_hdr(*arr); } } @@ -76,7 +76,7 @@ static void *arr_adda_(void **arr, size_t item_sz, Allocator *a) { } else { hdr = arr_hdr(*arr); if (hdr->len >= hdr->cap) { - arr_resva_(arr, hdr->len * 2, item_sz, a); + arr_resva_(arr, hdr->len * 2 + 1, item_sz, a); hdr = arr_hdr(*arr); } } @@ -101,6 +101,8 @@ static void *arr_last_(void *arr, size_t item_sz) { /* OPTIM: shrink array */ static void arr_remove_last_(void **arr, size_t item_sz) { + + assert(arr_hdr(*arr)->len); arr_hdr(*arr)->len--; (void)item_sz; } @@ -29,7 +29,7 @@ static bool cgen_block_enter(CGenerator *g, Block *b) { stmts = b->stmts; } if (b) g->indent_lvl++; - return block_enter(b, stmts); + return block_enter(b, stmts, 0); } static void cgen_block_exit(CGenerator *g, Block *into) { @@ -896,7 +896,6 @@ static bool cgen_block(CGenerator *g, Block *b, const char *ret_name, uint16_t f arr_foreach(b->stmts, Statement, s) if (!cgen_stmt(g, s)) return false; - if (b->ret_expr && ret_name) { if (b->ret_expr->type.kind == TYPE_TUPLE) { if (!cgen_set_tuple(g, NULL, NULL, ret_name, b->ret_expr)) @@ -942,7 +941,7 @@ static void cgen_zero_value(CGenerator *g, Type *t) { static bool cgen_fn(CGenerator *g, FnExpr *f, Location where) { FnExpr *prev_fn = g->fn; Block *prev_block = g->block; - fn_enter(f); + fn_enter(f, 0); if (!cgen_fn_header(g, f, where)) return false; cgen_write(g, " "); @@ -956,7 +955,6 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where) { if (!cgen_block_enter(g, &f->body)) return false; if (!cgen_block(g, &f->body, NULL, CGEN_BLOCK_FLAG_NOENTER | CGEN_BLOCK_FLAG_NOBRACES)) return false; - if (f->ret_decls) { if (cgen_uses_ptr(&f->ret_type)) { } else { @@ -1048,6 +1046,7 @@ static bool cgen_ret(CGenerator *g, Expression *ret) { } cgen_write(g, "return"); } else { + if (!cgen_expr_pre(g, ret)) return false; cgen_write(g, "return "); if (!cgen_expr(g, ret)) return false; diff --git a/decls_cgen.c b/decls_cgen.c index ca29bfc..189b032 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -85,7 +85,7 @@ static bool cgen_decls_block(CGenerator *g, Block *b) { static bool cgen_decls_decl(CGenerator *g, Declaration *d) { if (cgen_fn_is_direct(g, d)) { d->expr.fn.c.name = d->idents[0]; - fn_enter(&d->expr.fn); + fn_enter(&d->expr.fn, 0); if (!cgen_fn_header(g, &d->expr.fn, d->where)) return false; cgen_write(g, ";"); @@ -1,6 +1,6 @@ static bool eval_block(Evaluator *ev, Block *b, Value *v); static bool eval_expr(Evaluator *ev, Expression *e, Value *v); -static bool block_enter(Block *b, Statement *stmts); +static bool block_enter(Block *b, Statement *stmts, U32 flags); static void block_exit(Block *b, Statement *stmts); static void evalr_create(Evaluator *ev) { @@ -764,6 +764,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } } else { char *s = ident_to_str(e->ident); + err_print(e->where, "Cannot evaluate non-constant '%s' at compile time.", s); free(s); return false; @@ -805,19 +806,25 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { return false; FnExpr *fn = fnv.fn; /* set parameter declaration values */ - long arg = 0; Declaration *params = fn->params; - fn_enter(fn); + /* OPTIM (NOTE: currently needed for recursion) */ + Value *args = NULL; + arr_resv(&args, arr_len(e->call.arg_exprs)); + for (size_t i = 0; i < arr_len(e->call.arg_exprs); i++) { + if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i])) + return false; + } + fn_enter(fn, 0); + long arg = 0; arr_foreach(params, Declaration, p) { arr_foreach(p->idents, Identifier, i) { IdentDecl *id = ident_decl(*i); - Value *paramval = &id->val; - if (!eval_expr(ev, &e->call.arg_exprs[arg], paramval)) - return false; + id->val = args[arg]; id->flags |= IDECL_FLAG_HAS_VAL; arg++; } } + arr_clear(&args); if (!eval_block(ev, &fn->body, v)) { fn_exit(fn); return false; @@ -877,7 +884,7 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) { } static bool eval_block(Evaluator *ev, Block *b, Value *v) { - block_enter(b, b->stmts); + block_enter(b, b->stmts, 0); arr_foreach(b->stmts, Statement, stmt) { if (!eval_stmt(ev, stmt)) return false; @@ -1,9 +1,7 @@ /* TODO: -fix recursion with block_enter/exit -arr => slice casting del slices -run time return statements +slice notation (x[a:b]) bf interpreter error on failed calloc in output unicode variable names @@ -81,7 +79,7 @@ int main(int argc, char **argv) { evalr_create(&ev); typer_create(&tr, &ev); - if (!block_enter(NULL, f.stmts)) /* enter global scope */ + if (!block_enter(NULL, f.stmts, SCOPE_FLAG_CHECK_REDECL)) /* enter global scope */ return false; if (!types_file(&tr, &f)) { @@ -18,7 +18,7 @@ typedef struct { void *data; u64 n; } slice_; /* declarations */ void puti(i64 x); -i64 foo(i64 x); +i64 factorial(i64 x); void main__(void); /* code */ int main() { @@ -34,31 +34,21 @@ void puti(i64 x) { } -i64 foo(i64 x) { +i64 factorial(i64 x) { - slice_ C; { - slice_ expr__; slice_ a0_; a0_.data = calloc(x, sizeof(i64)); a0_.n = x;expr__ = a0_;C = expr__;} - i64 i; { - i64 expr__; expr__ = 0;i = expr__;} - while ((i<x)) { - (((i64(*))(C.data))[i]) = i;; - i = (i+1);; - }; - i64 total; { - i64 expr__; expr__ = 0;total = expr__;} - i = 0;; - while ((i<x)) { - total = (total+(((i64(*))(C.data))[i]));; - i = (i+1);; - }; - return total; + i64 a0_; + if ((x==0)) { + a0_ = 1; + } else { + a0_ = (x*(factorial((x-1)))); + }return a0_; } void main__(void) { - i64( A[45]) = {0}; - i64( B[4950]) = {0}; + i64( a342[120]) = {0}; + (puti((factorial(20)))); } @@ -1,8 +1,10 @@ -static bool add_ident_decls(Block *b, Declaration *d) { +#define SCOPE_FLAG_CHECK_REDECL 0x0001 + +static bool add_ident_decls(Block *b, Declaration *d, U32 flags) { bool ret = true; arr_foreach(d->idents, Identifier, ident) { IdentDecl **decls = &(*ident)->decls; - if (arr_len(*decls)) { + if ((flags & SCOPE_FLAG_CHECK_REDECL) && arr_len(*decls)) { /* check that it hasn't been declared in this block */ IdentDecl *prev = arr_last(*decls); if (prev->scope == b) { @@ -34,12 +36,12 @@ static void remove_ident_decls(Block *b, Declaration *d) { } /* pass NULL for block for global scope */ -static bool block_enter(Block *b, Statement *stmts) { +static bool block_enter(Block *b, Statement *stmts, uint32_t flags) { bool ret = true; arr_foreach(stmts, Statement, stmt) { if (stmt->kind == STMT_DECL) { Declaration *decl = &stmt->decl; - if (!add_ident_decls(b, decl)) + if (!add_ident_decls(b, decl, flags)) ret = false; } } @@ -56,11 +58,11 @@ static void block_exit(Block *b, Statement *stmts) { } /* does NOT enter function's block body */ -static void fn_enter(FnExpr *f) { +static void fn_enter(FnExpr *f, U32 flags) { arr_foreach(f->params, Declaration, decl) - add_ident_decls(&f->body, decl); + add_ident_decls(&f->body, decl, flags); arr_foreach(f->ret_decls, Declaration, decl) - add_ident_decls(&f->body, decl); + add_ident_decls(&f->body, decl, flags); } static void fn_exit(FnExpr *f) { @@ -5,40 +5,12 @@ puti @= fn(x: int) { #C("printf(\"%ld\\n\", (long)x)"); }; -// foo @= fn(x:int) int { -// if x < 4 { -// return 7; -// } else { -// return 5; -// } -// 4 -// }; -foo @= fn(x: int) int { - C := new(int, x); - i := 0; - while i < x { - C[i] = i; - i = i + 1; - } - total := 0; - i = 0; - while i < x { - total = total + C[i]; - i = i + 1; - } - total - +factorial @= fn(x: int) int { + if x == 0 { 1 } else { x * factorial(x-1) } }; main @= fn() { - A : [foo(10)]int; - B : [foo(100)]int; - // C := new(int, 10); - // i := 0; - // while i < 10 { - // C[i] = 7; - // i = i + 1; - // } - // puti(C[9]); + a342 : [factorial(5)]int; + puti(factorial(20)); }; @@ -483,7 +483,7 @@ static bool types_expr(Typer *tr, Expression *e) { tr->ret_type = t->fn.types[0]; } tr->can_ret = true; - fn_enter(f); + fn_enter(f, SCOPE_FLAG_CHECK_REDECL); bool block_success = true; block_success = types_block(tr, &e->fn.body); fn_exit(f); @@ -1014,7 +1014,7 @@ static bool types_block(Typer *tr, Block *b) { bool success = true; Block *prev_block = tr->block; tr->block = b; - if (!block_enter(b, b->stmts)) return false; + if (!block_enter(b, b->stmts, SCOPE_FLAG_CHECK_REDECL)) return false; arr_foreach(b->stmts, Statement, s) { if (!types_stmt(tr, s)) success = false; @@ -1034,7 +1034,7 @@ static bool types_block(Typer *tr, Block *b) { static bool types_decl(Typer *tr, Declaration *d) { bool success = true; - if (d->flags & DECL_FLAG_FOUND_TYPE) goto ret; + if (d->flags & DECL_FLAG_FOUND_TYPE) return true; Declaration **dptr = typer_arr_add(tr, &tr->in_decls); *dptr = d; if (d->flags & DECL_FLAG_ANNOTATES_TYPE) { |