summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--identifiers.c3
-rw-r--r--main.c11
-rw-r--r--parse.c25
-rw-r--r--test.toc4
-rw-r--r--types.c82
5 files changed, 76 insertions, 49 deletions
diff --git a/identifiers.c b/identifiers.c
index 0f083c0..6e993f2 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -187,8 +187,7 @@ static void ident_add_decl(Identifier i, struct Declaration *d, struct Block *b)
}
static IdentDecl *ident_decl(Identifier i) {
- assert(i->decls.item_sz);
- return (IdentDecl*)arr_last(&i->decls);
+ return i->decls.item_sz == 0 ? NULL : (IdentDecl*)arr_last(&i->decls);
}
static void idents_free(Identifiers *ids) {
diff --git a/main.c b/main.c
index 6ea2855..50df138 100644
--- a/main.c
+++ b/main.c
@@ -60,17 +60,18 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
- fprint_parsed_file(stdout, &f);
-
- tokr_free(&t);
-
-
block_enter(NULL, &f.stmts); /* enter global scope */
if (!types_file(&f)) {
err_fprint(TEXT_IMPORTANT("Errors occured while determining types.\n"));
return EXIT_FAILURE;
}
+ fprint_parsed_file(stdout, &f);
+
+ tokr_free(&t);
+
+
+
/* TODO (eventually): use a tmp file (don't overwrite old output if there's an error) */
/* const char *c_out_filename = "out.c"; */
/* const char *h_out_filename = "out.h"; */
diff --git a/parse.c b/parse.c
index 1127a56..effe5f7 100644
--- a/parse.c
+++ b/parse.c
@@ -939,6 +939,11 @@ NOTE: this function actually parses all types in the declaration, but it just
calls itself to do that.
*/
+static inline bool ends_decl(Token *t, DeclEndType ends_with) {
+ return (token_is_kw(t, KW_SEMICOLON) && ends_with == DECL_END_SEMICOLON)
+ || (token_is_kw(t, KW_RPAREN) && ends_with == DECL_END_RPAREN);
+}
+
static bool parse_single_type_in_decl(Parser *p, Declaration *d, DeclEndType ends_with) {
Tokenizer *t = p->tokr;
/* OPTIM: Maybe don't use a dynamic array or use parser allocator. */
@@ -1024,8 +1029,7 @@ static bool parse_single_type_in_decl(Parser *p, Declaration *d, DeclEndType end
if (!parse_expr(p, &d->expr, expr_find_end(p, 0)))
return false;
d->flags |= DECL_FLAG_HAS_EXPR;
- if ((token_is_kw(t->token, KW_SEMICOLON) && ends_with == DECL_END_SEMICOLON)
- || (token_is_kw(t->token, KW_RPAREN) && ends_with == DECL_END_RPAREN)) {
+ if (ends_decl(t->token, ends_with)) {
t->token++;
return true;
}
@@ -1033,8 +1037,7 @@ static bool parse_single_type_in_decl(Parser *p, Declaration *d, DeclEndType end
ends_with == DECL_END_SEMICOLON ? ';' : ')');
return false;
- } else if ((token_is_kw(t->token, KW_SEMICOLON) && ends_with == DECL_END_SEMICOLON)
- || (token_is_kw(t->token, KW_RPAREN) && ends_with == DECL_END_RPAREN)) {
+ } else if (ends_decl(t->token, ends_with)) {
t->token++;
return true;
} else {
@@ -1050,9 +1053,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndType ends_with) {
arr_create(&d->idents, sizeof(Identifier));
Tokenizer *t = p->tokr;
d->flags = 0;
- /* TODO: extract cond */
- if ((token_is_kw(t->token, KW_SEMICOLON) && ends_with == DECL_END_SEMICOLON)
- || (token_is_kw(t->token, KW_RPAREN) && ends_with == DECL_END_RPAREN)) {
+ if (ends_decl(t->token, ends_with)) {
t->token++;
return true;
}
@@ -1194,7 +1195,11 @@ static void fprint_block(FILE *out, Block *b) {
fprint_stmt(out, stmt);
}
fprintf(out, "}");
-
+ if (b->ret_expr) {
+ fprintf(out, " returns ");
+ fprint_expr(out, b->ret_expr);
+ }
+
}
static void fprint_fn_expr(FILE *out, FnExpr *f) {
@@ -1277,6 +1282,8 @@ static void fprint_expr(FILE *out, Expression *e) {
fprint_args(out, &e->direct.args);
break;
}
+ fprintf(out, ":");
+ fprint_type(out, &e->type);
}
@@ -1290,7 +1297,7 @@ static void fprint_decl(FILE *out, Declaration *d) {
fprintf(out, "[const]");
}
fprintf(out, ":");
- if (d->flags & DECL_FLAG_ANNOTATES_TYPE) {
+ if ((d->flags & DECL_FLAG_FOUND_TYPE) || (d->flags & DECL_FLAG_ANNOTATES_TYPE)) {
fprint_type(out, &d->type);
}
if (d->flags & DECL_FLAG_HAS_EXPR) {
diff --git a/test.toc b/test.toc
index be7d33f..5c5af41 100644
--- a/test.toc
+++ b/test.toc
@@ -4,9 +4,9 @@ print_int @= fn(x: int) {
#C("printf(\"%ld\\n\", (long)x);\n");
};
-times2 @= fn(x: int) int { 5 /* x*/ };
+times2 @= fn(x: int) int { x + x };
main @= fn() {
print_int(times2(5));
- foo := fn (x, y, z : float, y:double) {};
+ foo := fn (x, y, z : float, A:double) {};
};
diff --git a/types.c b/types.c
index 2e57245..9c43c13 100644
--- a/types.c
+++ b/types.c
@@ -1,49 +1,58 @@
static bool types_stmt(Statement *s);
static bool types_expr(Expression *e);
+static bool add_ident_decls(Block *b, Declaration *d) {
+ bool ret = true;
+ arr_foreach(&d->idents, Identifier, ident) {
+ Array *decls = &(*ident)->decls;
+ if (decls->len) {
+ /* check that it hasn't been declared in this block */
+ IdentDecl *prev = arr_last(decls);
+ if (prev->scope == b) {
+ err_print(d->where, "Re-declaration of identifier in the same block.");
+ info_print(prev->decl->where, "Previous declaration was here.");
+ ret = false;
+ continue;
+ }
+ }
+ ident_add_decl(*ident, d, b);
+ }
+ return ret;
+}
+
+static void remove_ident_decls(Block *b, Declaration *d) {
+ arr_foreach(&d->idents, Identifier, ident) {
+ IdentTree *id_info = *ident;
+ Array *decls = &id_info->decls;
+ assert(decls->item_sz);
+ IdentDecl *last_decl = arr_last(decls);
+ if (last_decl && last_decl->scope == b) {
+ arr_remove_last(decls); /* remove that declaration */
+ }
+ }
+}
+
/* pass NULL for block for global scope */
static bool block_enter(Block *b, Array *stmts) {
bool ret = true;
arr_foreach(stmts, Statement, stmt) {
if (stmt->kind == STMT_DECL) {
Declaration *decl = &stmt->decl;
- arr_foreach(&decl->idents, Identifier, ident) {
- Array *decls = &(*ident)->decls;
- if (decls->len) {
- /* check that it hasn't been declared in this block */
- 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.");
- ret = false;
- continue;
- }
- }
- ident_add_decl(*ident, decl, b);
- }
+ if (!add_ident_decls(b, decl))
+ ret = false;
}
}
return ret;
}
-static bool block_exit(Block *b, Array *stmts) {
+static void block_exit(Block *b, Array *stmts) {
/* OPTIM: figure out some way of not re-iterating over everything */
- bool ret = true;
arr_foreach(stmts, Statement, stmt) {
if (stmt->kind == STMT_DECL) {
Declaration *decl = &stmt->decl;
- arr_foreach(&decl->idents, Identifier, ident) {
- IdentTree *id_info = *ident;
- Array *decls = &id_info->decls;
- assert(decls->item_sz);
- IdentDecl *last_decl = arr_last(decls);
- if (last_decl->scope == b) {
- arr_remove_last(decls); /* remove that declaration */
- }
- }
+ remove_ident_decls(b, decl);
}
}
- return ret;
}
static bool type_eq(Type *a, Type *b) {
@@ -240,6 +249,9 @@ static bool type_of_expr(Expression *e, Type *t) {
t->builtin = BUILTIN_I64;
t->flags |= TYPE_FLAG_FLEXIBLE;
break;
+ case EXPR_STR_LITERAL:
+ t->kind = TYPE_UNKNOWN; /* TODO */
+ break;
case EXPR_FLOAT_LITERAL:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_FLOAT;
@@ -267,6 +279,10 @@ static bool type_of_expr(Expression *e, Type *t) {
}
case EXPR_DIRECT:
t->kind = TYPE_UNKNOWN;
+ /* TODO: make sure direct args have the right type */
+ arr_foreach(&e->direct.args, Expression, arg) {
+ types_expr(arg);
+ }
break;
case EXPR_UNARY_OP: {
Type *of_type = &e->unary.of->type;
@@ -385,7 +401,7 @@ static bool types_block(Block *b) {
if (!types_stmt(s)) ret = false;
}
if (b->ret_expr) types_expr(b->ret_expr);
- if (!block_exit(b, &b->stmts)) return false;
+ block_exit(b, &b->stmts);
return ret;
}
@@ -393,12 +409,16 @@ static bool types_expr(Expression *e) {
Type *t = &e->type;
if (!type_of_expr(e, t)) return false;
switch (e->kind) {
- case EXPR_FN:
+ case EXPR_FN: {
+ assert(e->type.kind == TYPE_FN);
+ FnExpr *f = e->fn;
+ add_ident_decls(&f->body, &f->params);
if (!types_block(&e->fn->body))
return false;
- assert(e->type.kind == TYPE_FN);
+ remove_ident_decls(&f->body, &f->params);
Type *ret_type = e->type.fn.types.data;
- Expression *ret_expr = e->fn->body.ret_expr;
+ Expression *ret_expr = f->body.ret_expr;
+
if (ret_expr) {
if (!type_eq(ret_type, &ret_expr->type)) {
char *got = type_to_str(&ret_expr->type);
@@ -415,7 +435,7 @@ static bool types_expr(Expression *e) {
free(expected);
return false;
}
- break;
+ } break;
case EXPR_CALL: {
bool ret = true;
arr_foreach(&e->call.args, Expression, arg) {