summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base_cgen.c11
-rw-r--r--identifiers.c3
-rw-r--r--out.c15
-rw-r--r--parse.c3
-rw-r--r--test.toc20
-rw-r--r--types.c108
-rw-r--r--util/arr.c22
-rw-r--r--util/blockarr.c7
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) {
diff --git a/out.c b/out.c
index 60532ee..b75d182 100644
--- a/out.c
+++ b/out.c
@@ -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) {
diff --git a/parse.c b/parse.c
index 4bd7bae..058c9aa 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/test.toc b/test.toc
index 5631694..536af71 100644
--- a/test.toc
+++ b/test.toc
@@ -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
diff --git a/types.c b/types.c
index 03ef9e7..4b34ef5 100644
--- a/types.c
+++ b/types.c
@@ -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(&param_types[i], buffer + written, bufsize - written);
+ written += type_to_str(&param_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) {
diff --git a/util/arr.c b/util/arr.c
index 54d05d6..97f4bd0 100644
--- a/util/arr.c
+++ b/util/arr.c
@@ -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;
}