summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--allocator.c2
-rw-r--r--cgen.c13
-rw-r--r--data_structures.c4
-rw-r--r--eval.c23
-rw-r--r--main.c3
-rw-r--r--parse.c19
-rw-r--r--test.toc19
-rw-r--r--types.c135
-rw-r--r--types.h21
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))
diff --git a/cgen.c b/cgen.c
index 07ed12e..6d72842 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
diff --git a/eval.c b/eval.c
index 4ffda79..9c55a06 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/main.c b/main.c
index 0e7932f..4934520 100644
--- a/main.c
+++ b/main.c
@@ -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:
diff --git a/parse.c b/parse.c
index 5b58e8a..c9867d5 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
}
+
diff --git a/test.toc b/test.toc
index c5e3ba6..1d21ead 100644
--- a/test.toc
+++ b/test.toc
@@ -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();
diff --git a/types.c b/types.c
index 95bade1..52ea5e0 100644
--- a/types.c
+++ b/types.c
@@ -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;
}
diff --git a/types.h b/types.h
index 3410f4f..1eadff5 100644
--- a/types.h
+++ b/types.h
@@ -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;