diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-25 09:57:28 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-25 09:57:52 -0400 |
commit | 7352f2c357619e23ed348bdadd48f38f9acd4d86 (patch) | |
tree | 39ac2440fb5d58866bc1ac9e57ff58424c235640 | |
parent | e278a73bbe573b45f67794301746b08b8fa5c4b2 (diff) |
compile time arrays and slices!
-rw-r--r-- | cgen.c | 29 | ||||
-rw-r--r-- | eval.c | 59 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | scope.c | 2 | ||||
-rw-r--r-- | test.toc | 45 |
5 files changed, 87 insertions, 49 deletions
@@ -1043,7 +1043,7 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) { return false; } if (!cgen_type_pre(g, t->slice, where)) return false; - cgen_write(g, "(d%p_[])", where.code); /* TODO: improve this somehow? */ + cgen_write(g, "(d%p_[])", v); /* TODO: improve this somehow? */ if (!cgen_type_post(g, t->slice, where)) return false; cgen_write(g, " = {"); for (U64 i = 0; i < s->n; i++) { @@ -1051,11 +1051,12 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) { if (!cgen_val_ptr(g, (char *)s->data + i * compiler_sizeof(t->slice), t->slice, where)) return false; } - cgen_write(g, "}"); + cgen_write(g, "};"); + cgen_nl(g); } break; case TYPE_ARR: for (size_t i = 0; i < t->arr.n; i++) { - if (!cgen_val_ptr_pre(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of, where)) + if (!cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr.of), t->arr.of, where)) return false; } break; @@ -1083,13 +1084,13 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { cgen_write(g, "{"); for (size_t i = 0; i < t->arr.n; i++) { if (i) cgen_write(g, ", "); - if (!cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of, where)) + if (!cgen_val_ptr(g, *(char **)v + i * compiler_sizeof(t->arr.of), t->arr.of, where)) return false; } cgen_write(g, "}"); break; case TYPE_SLICE: - cgen_write(g, "{d%p_, %lu}", where.code, ((Slice *)v)->n); + cgen_write(g, "{d%p_, %lu}", v, ((Slice *)v)->n); break; case TYPE_FN: cgen_fn_name(g, *(FnExpr **)v); @@ -1117,6 +1118,10 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { return true; } +static bool cgen_val_pre(CGenerator *g, Value *v, Type *t, Location where) { + return cgen_val_ptr_pre(g, v, t, where); +} + /* generates a value fit for use as an initializer */ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) { /* @@ -1126,6 +1131,7 @@ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) { return cgen_val_ptr(g, v, t, where); } + static bool cgen_decl(CGenerator *g, Declaration *d) { if (cgen_fn_is_direct(g, d)) { if (!cgen_fn(g, &d->expr.fn, d->where)) @@ -1134,6 +1140,8 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { if (d->type.kind == TYPE_TUPLE) { long idx = 0; arr_foreach(d->idents, Identifier, i) { + if (!cgen_val_pre(g, &d->val.tuple[idx], &d->type.tuple[idx], d->where)) + return false; if (!cgen_type_pre(g, &d->type.tuple[idx], d->where)) return false; cgen_write(g, " "); cgen_ident(g, *i); @@ -1142,20 +1150,17 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { if (!cgen_val(g, &d->val.tuple[idx], &d->type.tuple[idx], d->where)) return false; idx++; + cgen_write(g, ";"); + cgen_nl(g); } - cgen_write(g, ";"); - cgen_nl(g); } else { + if (!cgen_val_pre(g, &d->val, &d->type, d->where)) + return false; if (!cgen_type_pre(g, &d->type, d->where)) return false; cgen_write(g, " "); cgen_ident(g, d->idents[0]); if (!cgen_type_post(g, &d->type, d->where)) return false; cgen_write(g, " = "); - if (d->type.kind == TYPE_ARR) { - I64 *nums = d->val.arr; - printf("%ld\n",nums[0]); - } - return true; if (!cgen_val(g, &d->val, &d->type, d->where)) return false; cgen_write(g, ";"); @@ -1,4 +1,4 @@ -static bool eval_block(Evaluator *ev, Block *b, Value *v); +static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v); static bool eval_expr(Evaluator *ev, Expression *e, Value *v); static bool block_enter(Block *b, Statement *stmts, U32 flags); static void block_exit(Block *b, Statement *stmts); @@ -41,15 +41,15 @@ static size_t compiler_sizeof(Type *t) { case TYPE_BUILTIN: return compiler_sizeof_builtin(t->builtin); case TYPE_FN: - return sizeof t->fn; + return sizeof(FnExpr *); case TYPE_PTR: - return sizeof t->ptr; + return sizeof(void *); case TYPE_ARR: return t->arr.n * compiler_sizeof(t->arr.of); case TYPE_TUPLE: - return sizeof t->tuple; + return sizeof(Value *); case TYPE_SLICE: - return sizeof t->slice; + return sizeof(Slice); case TYPE_VOID: case TYPE_UNKNOWN: return 0; @@ -141,6 +141,29 @@ static void u64_to_val(Value *v, BuiltinType v_type, U64 x) { i64_to_val(v, v_type, (I64)x); } +static void val_copy(Value *dest, Value *src, Type *t) { + switch (t->kind) { + case TYPE_BUILTIN: + case TYPE_FN: + case TYPE_PTR: + case TYPE_SLICE: + case TYPE_VOID: + case TYPE_UNKNOWN: + *dest = *src; + break; + case TYPE_ARR: { + size_t bytes = t->arr.n * compiler_sizeof(t->arr.of); + dest->arr = err_malloc(bytes); + memcpy(dest->arr, src->arr, bytes); + } break; + case TYPE_TUPLE: { + size_t bytes = arr_len(t->tuple) * sizeof(*dest->tuple); + dest->tuple = malloc(bytes); + memcpy(dest->tuple, src->tuple, bytes); + } break; + } +} + #define builtin_casts_to_int(x) \ case BUILTIN_I8: \ vout->i8 = (I8)vin->x; break; \ @@ -477,8 +500,10 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) { case BINARY_AT_INDEX: { void *ptr; Type *type; + /* get pointer to x[i] */ if (!eval_expr_ptr_at_index(ev, set, &ptr, &type)) return false; + /* set it to to */ eval_deref_set(ptr, to, type); } break; default: break; @@ -723,12 +748,12 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value cond; if (!eval_expr(ev, i->cond, &cond)) return false; if (val_truthiness(&cond, &i->cond->type)) { - if (!eval_block(ev, &i->body, v)) return false; + if (!eval_block(ev, &i->body, &e->type, v)) return false; } else if (i->next_elif) { if (!eval_expr(ev, i->next_elif, v)) return false; } } else { - if (!eval_block(ev, &i->body, v)) return false; + if (!eval_block(ev, &i->body, &e->type, v)) return false; } } break; case EXPR_WHILE: { @@ -740,11 +765,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!val_truthiness(&cond, &w->cond->type)) break; } - if (!eval_block(ev, &w->body, v)) return false; + if (!eval_block(ev, &w->body, &e->type, v)) return false; } } break; case EXPR_BLOCK: - if (!eval_block(ev, &e->block, v)) return false; + if (!eval_block(ev, &e->block, &e->type, v)) return false; break; case EXPR_LITERAL_BOOL: v->boolv = e->booll; @@ -850,7 +875,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } } arr_clear(&args); - if (!eval_block(ev, &fn->body, v)) { + if (!eval_block(ev, &fn->body, &e->type, v)) { fn_exit(fn); return false; } @@ -921,12 +946,13 @@ static bool eval_decl(Evaluator *ev, Declaration *d) { arr_foreach(d->idents, Identifier, i) { IdentDecl *id = ident_decl(*i); if (has_expr && d->expr.kind == EXPR_TUPLE) { - id->val = val.tuple[index++]; + val_copy(&id->val, &val.tuple[index], &d->type.tuple[index]); + index++; } else if (!has_expr && d->type.kind == TYPE_ARR) { /* "stack" array */ id->val.arr = err_calloc(d->type.arr.n, compiler_sizeof(d->type.arr.of)); } else { - id->val = val; + val_copy(&id->val, &val, &d->type); } id->flags |= IDECL_FLAG_HAS_VAL; } @@ -952,17 +978,22 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) { return true; } -static bool eval_block(Evaluator *ev, Block *b, Value *v) { +/* t is the type of the block. */ +static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v) { block_enter(b, b->stmts, 0); arr_foreach(b->stmts, Statement, stmt) { if (!eval_stmt(ev, stmt)) return false; if (ev->returning) break; } + Value *returning = ev->returning; + Value r; if (!ev->returning && b->ret_expr) { - if (!eval_expr(ev, b->ret_expr, v)) + returning = &r; + if (!eval_expr(ev, b->ret_expr, returning)) return false; } + if (returning) val_copy(v, returning, t); block_exit(b, b->stmts); return true; @@ -1,6 +1,7 @@ /* TODO: array/slice values +fix leaking of constant stack arrays make sure initializers for global variables are compile-time constants structs length of slice/arr with .len @@ -26,6 +26,8 @@ static void remove_ident_decls(Block *b, Declaration *d) { IdentDecl *last_decl = arr_last(*decls); if (last_decl && last_decl->scope == b) { if ((last_decl->flags & IDECL_FLAG_HAS_VAL) + /* don't free const arrays (there's only one per decl) */ + && !(last_decl->decl->flags & DECL_FLAG_CONST) && last_decl->decl->type.kind == TYPE_ARR) { /* free array on stack */ free(last_decl->val.arr); @@ -13,32 +13,31 @@ putf @= fn(x: float) { "); }; -ptriple @= fn(m: int, n: int) (int, int, int) { - m*m-n*n, 2*m*n, m*m+n*n -}; - -f @= fn() int { - a, b, c : int; - a, b, c = ptriple(3, 2); - a + b + c -}; -aSDF @= fn() [3]int { - x: [3]int; - x[0] = 1; - x[1] = 2; - x[2] = 3; +N @= 50; +pascal @= fn() [N][]int { + x: [N][]int; + i := 0; + while i < N { + x[i] = new(int, i+1); + i = i + 1; + } + i = 0; + while i < N { + x[i][0] = 1; + x[i][i] = 1; + j := 1; + while j < i { + x[i][j] = x[i-1][j-1] + x[i-1][j]; + j = j + 1; + } + i = i + 1; + } x }; main @= fn() { - puti(f()); - A : [f()]int; - x @= f(); - dsafsad @= ptriple; - foo @= aSDF(); - puti(foo[0]); - puti(foo[1]); - puti(foo[2]); - // B : [aSDF()[0]]int; + ptriangle @= pascal(); + puti(ptriangle[49][25]); + }; |