diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-07-13 22:57:41 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-07-13 22:57:41 -0400 |
commit | 28de7a9c80524aac38a985ede651e782985bde67 (patch) | |
tree | e0455750755bf2466262f2e34496f608fe0f346c | |
parent | 6d800ca8bac8ea0b9eae255833273c90d0108eb9 (diff) |
static for seems to be working; also fixed some eval stuff
-rw-r--r-- | allocator.c | 2 | ||||
-rw-r--r-- | cgen.c | 13 | ||||
-rw-r--r-- | data_structures.c | 4 | ||||
-rw-r--r-- | eval.c | 23 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | parse.c | 19 | ||||
-rw-r--r-- | test.toc | 19 | ||||
-rw-r--r-- | types.c | 135 | ||||
-rw-r--r-- | types.h | 21 |
9 files changed, 145 insertions, 94 deletions
diff --git a/allocator.c b/allocator.c index 677bf75..25ac923 100644 --- a/allocator.c +++ b/allocator.c @@ -22,7 +22,7 @@ For more information, please refer to <http://unlicense.org/> */ #ifdef TOC_DEBUG -//#define NO_ALLOCATOR 1 // useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator +#define NO_ALLOCATOR 1 // useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator #endif // number of bytes a page hold, not including the header #define PAGE_BYTES (16384 - sizeof(Page)) @@ -1433,22 +1433,15 @@ static void cgen_decl(CGenerator *g, Declaration *d) { continue; } Value *val = decl_val_at_index(d, idx); - if (has_expr) { - cgen_val_pre(g, val, type); - } + cgen_val_pre(g, val, type); if (is_const) cgen_write(g, "static "); cgen_type_pre(g, type); cgen_write(g, is_const ? " const " : " "); cgen_ident(g, i); cgen_type_post(g, type); - if (has_expr) { - cgen_write(g, " = "); - cgen_val(g, val, type); - } else { - cgen_write(g, " = "); - cgen_zero_value(g, type); - } + cgen_write(g, " = "); + cgen_val(g, val, type); cgen_write(g, ";"); cgen_nl(g); } diff --git a/data_structures.c b/data_structures.c index bc7b48b..e8d0e99 100644 --- a/data_structures.c +++ b/data_structures.c @@ -100,9 +100,9 @@ static WarnUnusedResult void *arr_growa(void *arr, size_t item_sz, Allocator *al hdr = arr_hdr(arr); if (hdr->len >= hdr->cap) { size_t old_size = sizeof *hdr + item_sz * hdr->cap; - size_t new_size = sizeof *hdr + item_sz * hdr->cap * 2; - hdr = allocr_realloc(allocr, hdr, old_size, new_size); hdr->cap *= 2; + size_t new_size = sizeof *hdr + item_sz * hdr->cap; + hdr = allocr_realloc(allocr, hdr, old_size, new_size); } } return hdr->data; @@ -234,7 +234,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { if (n > 5) n = 5; for (I64 i = 0; i < n; ++i) { if (i) fprintf(f, ", "); - fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->arr->of), t->arr->of); + fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->slice), t->slice); } if (slice.len > n) { fprintf(f, ", ..."); @@ -593,14 +593,7 @@ static void eval_deref_set(void *set, Value *to, Type *type) { } } -static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr_type, void **ptr, Type **type) { - void *arr_ptr = NULL; - if (arr_type->kind == TYPE_PTR) { - arr_ptr = arr->ptr; - arr_type = arr_type->ptr; - } else { - arr_ptr = val_get_ptr(arr, arr_type); - } +static Status eval_val_ptr_at_index(Location where, void *arr_ptr, U64 i, Type *arr_type, void **ptr, Type **type) { switch (arr_type->kind) { case TYPE_ARR: { U64 arr_sz = (U64)arr_type->arr->n; @@ -629,7 +622,7 @@ static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr VarArg *varargs = *(VarArg **)arr_ptr; if (arr_type->builtin == BUILTIN_VARARGS) { if (i >= (U64)arr_len(varargs)) { - err_print(where, "Varargs out of bounds (index = %lu, varargs size = %lu)\n", (unsigned long)i, (unsigned long)arr_len(arr->varargs)); + err_print(where, "Varargs out of bounds (index = %lu, varargs size = %lu)\n", (unsigned long)i, (unsigned long)arr_len(varargs)); return false; } VarArg *vararg = &varargs[i]; @@ -645,8 +638,8 @@ static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr } static Status eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Type **type) { - Value arr; - if (!eval_expr(ev, e->binary.lhs, &arr)) return false; + void *arr_p; + if (!eval_address_of(ev, e->binary.lhs, &arr_p)) return false; Value index; if (!eval_expr(ev, e->binary.rhs, &index)) return false; Type *ltype = &e->binary.lhs->type; @@ -663,7 +656,7 @@ static Status eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, T } i = (U64)signed_index; } - return eval_val_ptr_at_index(e->where, &arr, i, ltype, ptr, type); + return eval_val_ptr_at_index(e->where, arr_p, i, ltype, ptr, type); } static Value *ident_val(Evaluator *ev, Identifier i, Location where) { @@ -1455,7 +1448,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } if (from < to) { void *ptr_start = NULL; - if (!eval_val_ptr_at_index(e->where, &ofv, from, of_type, &ptr_start, NULL)) + if (!eval_val_ptr_at_index(e->where, val_get_ptr(&ofv, of_type), from, of_type, &ptr_start, NULL)) return false; v->slice.data = ptr_start; v->slice.len = (I64)(to - from); @@ -1723,7 +1716,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) { index->i64 = 0; while (index->i64 < len) { void *ptr = NULL; - if (!eval_val_ptr_at_index(stmt->where, &of, (U64)index->i64, of_type, &ptr, NULL)) + if (!eval_val_ptr_at_index(stmt->where, val_get_ptr(&of, of_type), (U64)index->i64, of_type, &ptr, NULL)) return false; if (uses_ptr) value_val->ptr = ptr; @@ -8,8 +8,9 @@ see development.md for development information @TODO: -#for +see note in types.c : we probably shouldn't go to the trouble of evaluating this (just do this stuff if it's an ident) figure out how printf is gonna work +make error when you give too few arguments better when putf is done, migrate tests to new std make a global table of builtin types, so if you ever need a pointer to one you can just point to the table improve type_to_str: @@ -2741,15 +2741,17 @@ static void fprint_expr(FILE *out, Expression *e) { fprintf(out, "("); fprint_expr(out, e->binary.lhs); fprintf(out, ")%s(", binary_op_to_str(e->binary.op)); - Type *lhs_type = &e->binary.lhs->type; - if (lhs_type->kind == TYPE_PTR) { - lhs_type = lhs_type->ptr; - } - if (e->binary.op == BINARY_DOT && found_type && lhs_type->kind == TYPE_STRUCT) { - fprint_ident(out, e->binary.field->name); - } else { - fprint_expr(out, e->binary.rhs); + if (found_type) { + Type *lhs_type = &e->binary.lhs->type; + if (lhs_type->kind == TYPE_PTR) { + lhs_type = lhs_type->ptr; + } + if (e->binary.op == BINARY_DOT && lhs_type->kind == TYPE_STRUCT) { + fprint_ident(out, e->binary.field->name); + break; + } } + fprint_expr(out, e->binary.rhs); fprintf(out, ")"); } break; case EXPR_UNARY_OP: @@ -3105,3 +3107,4 @@ static inline bool struct_is_template(StructDef *s) { static inline bool fn_is_template(FnExpr *f) { return f->instances && !f->instance_id; } + @@ -1,20 +1,15 @@ #include "std/io.toc"; -putis ::= fn(x: ..) { - for a := x { - #if typeof(a) != int { - #error "Arguments to putis must all be ints."; +main ::= fn() { + a : [5]int; + for i ::= 1..10 { + a : [i]int; + a[0] = 7; + for j ::= 0.,i { + puti(a[j]); } - puti(a); } } - -main ::= fn() { - puti(-12); - putis(3,4,5); - putis(3,4,5,-12); - putis(3,4,5,565); -} main(); @@ -85,6 +85,13 @@ static size_t compiler_alignof_builtin(BuiltinType b) { return 0; } +static inline void typer_block_create(Typer *tr, Block *b, Location where) { + memset(b, 0, sizeof *b); + b->parent = tr->block; + b->where = where; + idents_create(&b->idents, tr->allocr, b); +} + static inline char *get_struct_name(StructDef *s) { return s->name ? ident_to_str(s->name) : str_dup("anonymous struct"); } @@ -1838,7 +1845,7 @@ static Status types_expr(Typer *tr, Expression *e) { bool has_varargs = f->type.kind == TYPE_FN && fn_type_has_varargs(f->type.fn); bool fn_being_used_before_declared = false; - if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE) || has_varargs) { + if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE) || has_varargs) { // evaluate the function when possible (this allows us to use named arguments, default arguments, etc.) Value val; if (f->kind == EXPR_IDENT) { @@ -1850,6 +1857,7 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } } + // @TODO: we probably shouldn't go to the trouble of evaluating this (just do this stuff if it's an ident) if (!eval_expr(tr->evalr, f, &val)) return false; fn_decl = val.fn; @@ -3463,6 +3471,10 @@ static Status include_stmts_link_to_nms(Typer *tr, Namespace *nms, Statement *st static Status types_stmt(Typer *tr, Statement *s) { top: if (s->flags & STMT_TYPED) return true; +#if 0 + printf("Typing "); + print_location(s->where); +#endif switch (s->kind) { case STMT_EXPR: { Expression *e = s->expr; @@ -3483,7 +3495,6 @@ top: } } } break; - case STMT_FOR: { bool in_header = true; Block *prev_block = tr->block; { // additional block because c++ @@ -3543,6 +3554,13 @@ top: *val_type = header->type; } } + + assert(arr_len(header->idents) == 2); + Identifier val_ident = header->idents[0]; + Identifier index_ident = header->idents[1]; + bool has_val = !ident_eq_str(val_ident, "_"); + bool has_index = !ident_eq_str(index_ident, "_"); + Type *fo_type = &header->type; fo_type->flags = TYPE_IS_RESOLVED; fo_type->kind = TYPE_TUPLE; @@ -3553,12 +3571,6 @@ top: if (!index_type->flags) { construct_resolved_builtin_type(index_type, BUILTIN_I64); } - - if (header->flags & DECL_IS_CONST) { - // static for - // @TODO ASDF - - } if (is_range) { if (!types_expr(tr, fo->range.from)) goto for_fail; @@ -3680,23 +3692,14 @@ top: arr_set_lena(s->inline_block, nvarargs, tr->allocr); Statement *stmt = s->inline_block; size_t nstmts = arr_len(fo->body.stmts); - Declaration *header_decl = &fo->header; - - assert(arr_len(header_decl->idents) == 2); - Identifier val_ident = header_decl->idents[0]; - Identifier index_ident = header_decl->idents[1]; - bool has_val = !ident_eq_str(val_ident, "_"); - bool has_index = !ident_eq_str(index_ident, "_"); for (size_t i = 0; i < nvarargs; ++i, ++stmt) { // create block #i memset(stmt, 0, sizeof *stmt); + stmt->where = s->where; stmt->kind = STMT_BLOCK; - Block *b = stmt->block = typer_calloc(tr, 1, sizeof *b); - b->parent = tr->block; - idents_create(&b->idents, tr->allocr, b); - b->stmts = NULL; - b->where = s->where; + Block *b = stmt->block = typer_malloc(tr, sizeof *b); + typer_block_create(tr, b, s->where); size_t total_nstmts = nstmts + has_val + has_index; arr_set_lena(b->stmts, total_nstmts, tr->allocr); Copier copier = copier_create(tr->allocr, b); @@ -3729,7 +3732,7 @@ top: decl_stmt->kind = STMT_DECL; decl_stmt->where = s->where; - // declare value + // declare index Declaration *decl = decl_stmt->decl = typer_calloc(tr, 1, sizeof *decl); decl->where = fo->of->where; Identifier ident = ident_translate_forced(index_ident, &b->idents); @@ -3803,6 +3806,76 @@ top: } tr->block = prev_block; + + if (header->flags & DECL_IS_CONST) { + // static for + // let's turn `for i ::= 1..3 { ... }` into `{ i ::= 1; ... } { i ::= 2; ... } { i ::= 3; ... }` + I64 from, to, step; + s->kind = STMT_INLINE_BLOCK; + s->inline_block = NULL; + + if (is_range) { + RangeFor *r = &fo->range; + if (has_index) { + err_print(s->where, "Static for loop with an index variable are not supported right now."); + return false; + } + if (!r->to) { + err_print(s->where, "Static for loops (for loops with ::) can't be infinite. You have to specify an end value to the range."); + goto for_fail; + } + if (!type_is_builtin(&r->from->type, BUILTIN_I64) || !type_is_builtin(&r->to->type, BUILTIN_I64)) { + err_print(s->where, "Static for loops can only be used with type int right now.\n" + "Either switch from :: to : or cast the range bounds to int."); + goto for_fail; + } + Value from_val, to_val; + if (!eval_expr(tr->evalr, r->from, &from_val)) return false; + if (!eval_expr(tr->evalr, r->to, &to_val)) return false; + from = from_val.i64; + to = to_val.i64; + step = r->stepval ? r->stepval->i64 : 1; + } else { + err_print(s->where, "Only range-based static for loops (e.g. for x ::= 1..10) are supported right now. You need to change :: to :"); + goto for_fail; + } + if (!(flags & FOR_INCLUDES_FROM)) + from += step; + + Statement *for_body_stmts = fo->body.stmts; + size_t for_body_nstmts = arr_len(for_body_stmts); + for (I64 x = from; flags & FOR_INCLUDES_TO ? x <= to : x < to; x += step) { + // create inner blocks, e.g. { i ::= 1; ... } + Statement *stmt = typer_arr_add_ptr(tr, s->inline_block); + memset(stmt, 0, sizeof *stmt); + stmt->kind = STMT_BLOCK; + stmt->where = s->where; + Block *b = stmt->block = typer_malloc(tr, sizeof *b); + typer_block_create(tr, b, s->where); + size_t nstmts = 1+for_body_nstmts; + arr_set_lena(b->stmts, nstmts, tr->allocr); + Statement *vdecl_stmt = &b->stmts[0]; + memset(vdecl_stmt, 0, sizeof *vdecl_stmt); + vdecl_stmt->where = s->where; + Declaration *vdecl = vdecl_stmt->decl = typer_calloc(tr, 1, sizeof *vdecl); + vdecl->where = s->where; + vdecl->flags = DECL_IS_CONST | DECL_FOUND_TYPE | DECL_FOUND_VAL; + vdecl->idents = NULL; + arr_set_lena(vdecl->idents, 1, tr->allocr); + Identifier id = vdecl->idents[0] = ident_translate_forced(val_ident, &b->idents); + id->decl = vdecl; + construct_resolved_builtin_type(&vdecl->type, BUILTIN_I64); + vdecl->val.i64 = x; + + Copier c = copier_create(tr->allocr, b); + // create a copy of each statement in each block + for (size_t i = 0; i < for_body_nstmts; ++i) { + copy_stmt(&c, &b->stmts[i+1], &for_body_stmts[i]); + } + } + goto top; + } + if (!types_block(tr, &fo->body)) goto for_fail; } break; @@ -3833,12 +3906,6 @@ top: s->inline_block = true_block->stmts; if (!fix_ident_decls_inline_block(tr, s->inline_block)) return false; - /* - erase identifiers in old block - we don't want anyone to think that - stuff is actually declared in the old block. - this isn't ideal, but oh well - */ - idents_create(&true_block->idents, tr->allocr, true_block); bool success = true; arr_foreach(s->inline_block, Statement, sub) { if (!types_stmt(tr, sub)) { @@ -3953,10 +4020,8 @@ top: inc_nms = typer_calloc(tr, 1, sizeof *inc_nms); Block *body = &inc_nms->body; + typer_block_create(tr, body, s->where); body->kind = BLOCK_NMS; - body->where = s->where; - idents_create(&body->idents, tr->allocr, body); - body->parent = tr->block; inc_nms->inc_file = inc_f; // turn #include "foo", bar into bar ::= nms { ... } @@ -4156,8 +4221,12 @@ top: } success: s->flags |= STMT_TYPED; + if (s->flags & STMT_IS_INIT) { + Initialization *init = typer_arr_add_ptr(tr, tr->gctx->inits); + init->stmt = s; + } if (tr->block == NULL || tr->block->kind == BLOCK_NMS) { - // evaluate statements at global scope + // evaluate top level statements switch (s->kind) { case STMT_DECL: case STMT_USE: @@ -4183,10 +4252,6 @@ success: break; } } - if (s->flags & STMT_IS_INIT) { - Initialization *init = typer_arr_add_ptr(tr, tr->gctx->inits); - init->stmt = s; - } return true; } @@ -877,21 +877,22 @@ enum { FOR_INCLUDES_TO = 0x04 }; typedef U8 ForFlags; +typedef struct { + Expression *from; // can't be null + Expression *to; // can be null + union { + // (either) can be null + Expression *step; // before typing + Value *stepval; /* after typing. the type of this is header.type.tuple[0] (i.e. the value type for this for loop), +NOTE: this might be different from the original ForExpr.step.type, because of implicit type conversions. */ + }; +} RangeFor; typedef struct For { ForFlags flags; Declaration header; Block body; union { - struct { - Expression *from; // can't be null - Expression *to; // can be null - union { - // (either) can be null - Expression *step; // before typing - Value *stepval; /* after typing. the type of this is header.type.tuple[0] (i.e. the value type for this for loop), - NOTE: this might be different from the original ForExpr.step.type, because of implicit type conversions. */ - }; - } range; + RangeFor range; Expression *of; }; } For; |