diff options
-rw-r--r-- | base_cgen.c | 11 | ||||
-rw-r--r-- | identifiers.c | 3 | ||||
-rw-r--r-- | out.c | 15 | ||||
-rw-r--r-- | parse.c | 3 | ||||
-rw-r--r-- | test.toc | 20 | ||||
-rw-r--r-- | types.c | 108 | ||||
-rw-r--r-- | util/arr.c | 22 | ||||
-rw-r--r-- | util/blockarr.c | 7 |
8 files changed, 111 insertions, 78 deletions
diff --git a/base_cgen.c b/base_cgen.c index d83b690..0e1f7f9 100644 --- a/base_cgen.c +++ b/base_cgen.c @@ -110,17 +110,6 @@ static bool cgen_ident(CGenerator *g, Identifier i, Location *where) { cgen_fn_name(g, &decl->expr.fn, NULL); return true; } - if (decl->where.line == where->line) { - /* e.g. x: int = x; */ - err_print(*where, "Use of identifier \"%s\" in its own declaration.", ident_to_str(i)); - return false; - } else if (decl->where.line > where->line) { - /* x used before declared */ - char *str = ident_to_str(i); - err_print(*where, "Use of identifier \"%s\" before its declaration.", str); - info_print(decl->where, "%s will be declared here.", str); - return false; - } } cgen_indent(g); fprint_ident(cgen_writing_to(g), i); diff --git a/identifiers.c b/identifiers.c index ebf3f0d..f491a06 100644 --- a/identifiers.c +++ b/identifiers.c @@ -13,7 +13,6 @@ typedef struct IdentTree { Array decls; /* array of declarations of this identifier */ unsigned long c_fn_reps; /* number of repetitions of this identifier in the C output--only used for functions */ size_t depth; - struct Type *type; } IdentTree; typedef IdentTree *Identifier; @@ -104,7 +103,7 @@ static char *ident_to_str(Identifier i) { } static IdentDecl *ident_decl(Identifier i) { - return (IdentDecl*)i->decls.last; + return (IdentDecl*)arr_last(&i->decls); } static void idents_free_tree(IdentTree *tree) { @@ -3,24 +3,15 @@ /* toc */ static void a___(void); static void a___1(void); -static void a___2(int64_t x); -void (*asdkfh)(int64_t ) = a___2; void main__(void) { + void (*foo)(void) = a___; void (*bar)(void) = a___1; - a___(); - a___1(); - int64_t a = 5; - float b = 32.300000; - int64_t c = a; - int64_t blah = 32; - float asfdljk = 12.300000; - int8_t asdkfjhakj = 1332948; } static void a___(void) { + a___1(); } static void a___1(void) { -} -static void a___2(int64_t x) { + a___(); } int main(void) { @@ -109,8 +109,8 @@ typedef struct Declaration { Location where; Array idents; Type type; - Expression expr; unsigned short flags; + Expression expr; } Declaration; typedef enum { @@ -326,6 +326,7 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { if (token_is_kw(t->token, KW_LBRACE)) { /* void function */ f->ret_type.kind = TYPE_VOID; + f->ret_type.flags = 0; } else { if (!parse_type(p, &f->ret_type)) { return false; @@ -1,18 +1,10 @@ main @= fn() { - foo @ fn() = fn() {}; - bar : fn() = fn() {}; + foo := fn() { + bar(); + }; - foo(); - bar(); - a : i64 = 5; - b : float = 32.3; - c : int = a; - blah := 32; - asfdljk: float = 12.3; - asdkfjhakj : i8 = 1332948; + bar := fn() { + foo(); + }; }; - - -asdkfh := fn(x: int) { -};
\ No newline at end of file @@ -1,4 +1,3 @@ -/* pass NULL for file */ static bool block_enter(Block *b) { bool ret = true; arr_foreach(&b->stmts, Statement, stmt) { @@ -8,7 +7,7 @@ static bool block_enter(Block *b) { Array *decls = &(*ident)->decls; if (decls->len) { /* check that it hasn't been declared in this block */ - IdentDecl *prev = decls->last; + IdentDecl *prev = arr_last(decls); if (prev->scope == b) { err_print(decl->where, "Re-declaration of identifier in the same block."); info_print(prev->decl->where, "Previous declaration was here."); @@ -38,7 +37,7 @@ static bool block_exit(Block *b) { arr_foreach(&decl->idents, Identifier, ident) { Array *decls = &(*ident)->decls; assert(decls->item_sz); - IdentDecl *last_decl = decls->last; + IdentDecl *last_decl = arr_last(decls); if (last_decl->scope == b) { arr_remove_last(decls); /* remove that declaration */ } @@ -51,7 +50,7 @@ static bool block_exit(Block *b) { /* returns the number of characters written, not including the null character */ -static size_t type_to_string(Type *a, char *buffer, size_t bufsize) { +static size_t type_to_str(Type *a, char *buffer, size_t bufsize) { switch (a->kind) { case TYPE_VOID: return str_copy(buffer, bufsize, "void"); @@ -68,12 +67,12 @@ static size_t type_to_string(Type *a, char *buffer, size_t bufsize) { for (size_t i = 0; i < nparams; i++) { if (i > 0) written += str_copy(buffer + written, bufsize - written, ", "); - written += type_to_string(¶m_types[i], buffer + written, bufsize - written); + written += type_to_str(¶m_types[i], buffer + written, bufsize - written); } written += str_copy(buffer + written, bufsize - written, ")"); if (ret_type->kind != TYPE_VOID) { written += str_copy(buffer + written, bufsize - written, " "); - written += type_to_string(ret_type, buffer + written, bufsize - written); + written += type_to_str(ret_type, buffer + written, bufsize - written); } return written; } break; @@ -132,9 +131,11 @@ static bool type_eq(Type *a, Type *b) { if (a->fn.types.len != b->fn.types.len) return false; Type *a_types = a->fn.types.data, *b_types = b->fn.types.data; - for (size_t i = 0; i < a->fn.types.len; i++) + for (size_t i = 0; i < a->fn.types.len; i++) { if (!type_eq(&a_types[i], &b_types[i])) return false; + + } return true; } } @@ -147,21 +148,18 @@ static bool type_must_eq(Location where, Type *expected, Type *got) { if (!type_eq(expected, got)) { char str_ex[128]; char str_got[128]; - type_to_string(expected, str_ex, sizeof str_ex); - type_to_string(got, str_got, sizeof str_got); + type_to_str(expected, str_ex, sizeof str_ex); + type_to_str(got, str_got, sizeof str_got); err_print(where, "Type mismatch: expected %s, but got %s.", str_ex, str_got); return false; } return true; } -static bool types_stmt(Statement *s); -static bool types_decl(Declaration *d); - -static bool types_expr(Expression *e) { - Type *t = &e->type; +static bool type_of_expr(Expression *e, Type *t) { t->flags = 0; + switch (e->kind) { case EXPR_FN: { FnExpr *f = &e->fn; @@ -173,12 +171,6 @@ static bool types_expr(Expression *e) { Type *param_type = arr_add(&t->fn.types); *param_type = param->type; } - block_enter(&f->body); - arr_foreach(&f->body.stmts, Statement, s) { - if (!types_stmt(s)) - return false; - } - block_exit(&f->body); } break; case EXPR_INT_LITERAL: t->kind = TYPE_BUILTIN; @@ -197,16 +189,85 @@ static bool types_expr(Expression *e) { err_print(e->where, "Undeclared identifier: %s", s); free(s); } - *t = decl->decl->type; + Declaration *d = decl->decl; + /* TODO: Check self-referential declarations */ + if (d->where.code > e->where.code) { + char *s = ident_to_str(e->ident); + err_print(e->where, "Use of identifier %s before its declaration.", s); + info_print(d->where, "%s will be declared here.", s); + free(s); + } + *t = d->type; } break; + case EXPR_CALL: { + Expression *f = e->call.fn; + Type fn_type; + if (f->kind == EXPR_IDENT) { + /* allow calling a function before declaring it */ + IdentDecl *decl = ident_decl(f->ident); + if (!decl) { + char *s = ident_to_str(e->ident); + err_print(e->where, "Undeclared identifier: %s", s); + free(s); + } + if (!type_of_expr(&decl->decl->expr, &fn_type)) return false; + } else { + if (!type_of_expr(e->call.fn, &fn_type)) return false; + } + if (fn_type.kind != TYPE_FN) { + char type[128]; + type_to_str(&fn_type, type, sizeof type); + err_print(e->where, "Calling non-function (type %s).", type); + return false; + } + /* TODO: Make sure args match fn type */ + *t = *(Type*)fn_type.fn.types.data; + break; /* TODO */ } + } return true; } +static bool types_stmt(Statement *s); + +static bool types_block(Block *b) { + bool ret = true; + block_enter(b); + arr_foreach(&b->stmts, Statement, s) { + if (!types_stmt(s)) ret = false; + } + block_exit(b); + return ret; +} + +static bool types_expr(Expression *e) { + Type *t = &e->type; + type_of_expr(e, t); + switch (e->kind) { + case EXPR_FN: { + types_block(&e->fn.body); + } break; + case EXPR_CALL: { + bool ret = true; + arr_foreach(&e->call.args, Expression, arg) { + if (!types_expr(arg)) ret = false; + } + return ret; + } + case EXPR_BINARY_OP: + return types_expr(e->binary.lhs) + && types_expr(e->binary.rhs); + case EXPR_UNARY_OP: + return types_expr(e->unary.of); + } + return true; +} + + static bool types_decl(Declaration *d) { - if (d->flags & DECL_FLAG_FOUND_TYPE) return true; if (!types_expr(&d->expr)) return false; + if (d->flags & DECL_FLAG_FOUND_TYPE) return true; if (d->flags & DECL_FLAG_INFER_TYPE) { d->type = d->expr.type; } else { @@ -215,8 +276,7 @@ static bool types_decl(Declaration *d) { } } d->flags |= DECL_FLAG_FOUND_TYPE; - - return types_expr(&d->expr); + return true; } static bool types_stmt(Statement *s) { @@ -1,6 +1,5 @@ typedef struct { void *data; - void *last; size_t len; size_t cap; size_t item_sz; @@ -10,13 +9,19 @@ static void arr_create(Array *arr, size_t item_sz) { arr->len = arr->cap = 0; arr->item_sz = item_sz; arr->data = NULL; - arr->last = NULL; } static void arr_reserve(Array *arr, size_t n) { arr->cap = n; arr->data = realloc(arr->data, arr->item_sz * arr->cap); - arr->last = (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); + +} + +static void *arr_last(Array *arr) { + if (arr->data) + return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); + else + return NULL; } static void *arr_add(Array *arr) { @@ -24,24 +29,19 @@ static void *arr_add(Array *arr) { arr_reserve(arr, (arr->cap + 1) * 2); } arr->len++; - arr->last = (char*)arr->last + arr->item_sz; - void *item = arr->last; - return item; + return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); } static void arr_clear(Array *arr) { free(arr->data); arr->len = arr->cap = 0; arr->data = NULL; - arr->last = NULL; } static void arr_remove_last(Array *arr) { /* OPTIM (memory): Shorten array. */ arr->len--; - if (arr->len) { - arr->last = (char*)arr->last - arr->item_sz; - } else { + if (!arr->len) { arr_clear(arr); } @@ -51,4 +51,4 @@ static void arr_free(Array *arr) { free(arr->data); } -#define arr_foreach(arr, type, var) for (type *var = (arr)->data; var; var == (arr)->last ? var = NULL : var++) +#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++) diff --git a/util/blockarr.c b/util/blockarr.c index ea333df..c85df5a 100644 --- a/util/blockarr.c +++ b/util/blockarr.c @@ -28,8 +28,11 @@ void block_arr_create(BlockArr *arr, int lg_block_sz, size_t item_sz) { } void *block_arr_add(BlockArr *arr) { + ArrBlock *last_block; + last_block = arr_last(&arr->blocks); + if (arr->blocks.data == NULL || - (unsigned long)((ArrBlock*)arr->blocks.last)->n >= (1UL << arr->lg_block_sz)) { + (unsigned long)last_block->n >= (1UL << arr->lg_block_sz)) { ArrBlock *block; /* no blocks yet / ran out of blocks*/ block = arr_add(&arr->blocks); @@ -38,8 +41,6 @@ void *block_arr_add(BlockArr *arr) { block->last = block->data; return block->data; } else { - ArrBlock *last_block; - last_block = arr->blocks.last; last_block->last = (char*)last_block->last + arr->item_sz; return last_block->last; } |