summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base_cgen.c6
-rw-r--r--cgen.c3
-rw-r--r--main.c1
-rw-r--r--out.c19
-rw-r--r--parse.c94
-rw-r--r--test.toc17
-rw-r--r--types.c14
7 files changed, 111 insertions, 43 deletions
diff --git a/base_cgen.c b/base_cgen.c
index 4c8cb72..93071a4 100644
--- a/base_cgen.c
+++ b/base_cgen.c
@@ -152,6 +152,9 @@ static bool cgen_type_pre(CGenerator *g, Type *t) {
if (!cgen_type_pre(g, ret_type)) return false;
cgen_write(g, "(*");
} break;
+ case TYPE_TUPLE:
+ assert(0);
+ return false;
case TYPE_ARR:
cgen_type_pre(g, t->arr.of);
break;
@@ -187,6 +190,9 @@ static bool cgen_type_post(CGenerator *g, Type *t) {
cgen_write_space(g);
if (!cgen_type_post(g, ret_type)) return false;
} break;
+ case TYPE_TUPLE:
+ assert(0);
+ return false;
case TYPE_ARR:
cgen_write(g, "[%lu]", t->arr.n);
cgen_type_post(g, t->arr.of);
diff --git a/cgen.c b/cgen.c
index 387da9f..fc0dd50 100644
--- a/cgen.c
+++ b/cgen.c
@@ -86,6 +86,9 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
cgen_zero_value(g, t->arr.of);
cgen_write(g, "}");
break;
+ case TYPE_TUPLE:
+ assert(0);
+ break;
case TYPE_BUILTIN:
if (type_builtin_is_numerical(t->builtin)) {
cgen_write(g, "0");
diff --git a/main.c b/main.c
index 5db564f..281387d 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,6 @@
/* TODO: don't allow setting things to void */
/* TODO: don't eval consts in C */
+/* TODO: array assignment (x : [3]int = y;) */
/* TODO: Functions returning fixed-length arrays */
/* TODO: improve error for declaring a keyword, e.g. i8: int = 8123; */
#include "toc.c"
diff --git a/out.c b/out.c
index 23b0282..ed273e4 100644
--- a/out.c
+++ b/out.c
@@ -1,24 +1,9 @@
#include "out.h"
/* toc */
-static void a___(void);
void main__(void) {
- void (*bar[3])(void) = {NULL};
- void (*foo)(void) = a___;
- ((bar[1])=foo);
- ((bar[2])=foo);
- ((bar[0])=foo);
- int64_t i = 0;
- void (*x)(void) = (bar[i]);
- x();
- (i=(i+1));
- (x=(bar[i]));
- x();
- (i=(i+1));
- (x=(bar[i]));
- x();
-}
-static void a___(void) {
+ float foo = 3; float bar = 3;
+ float abc = bar;
}
int main(void) {
diff --git a/parse.c b/parse.c
index 94360a9..cae15bc 100644
--- a/parse.c
+++ b/parse.c
@@ -3,6 +3,7 @@ typedef enum {
TYPE_VOID,
TYPE_BUILTIN,
TYPE_FN,
+ TYPE_TUPLE,
TYPE_ARR /* e.g. [5]int */
} TypeKind;
@@ -32,6 +33,7 @@ typedef struct Type {
struct {
Array types; /* [0] = ret_type, [1..] = param_types */
} fn;
+ Array tuple;
struct {
struct Type *of;
union {
@@ -262,6 +264,16 @@ static size_t type_to_str(Type *t, char *buffer, size_t bufsize) {
written += type_to_str(t->arr.of, buffer + written, bufsize - written);
return written;
} break;
+ case TYPE_TUPLE: {
+ size_t written = str_copy(buffer, bufsize, "(");
+ arr_foreach(&t->tuple, Type, child) {
+ if (child != t->tuple.data)
+ written += str_copy(buffer + written, bufsize - written, ", ");
+ written += type_to_str(child, buffer + written, bufsize - written);
+ }
+ written += str_copy(buffer + written, bufsize - written, ")");
+ return written;
+ }
}
assert(0);
@@ -878,14 +890,19 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
return true;
}
-static bool decl_parse(Declaration *d, Parser *p) {
+/*
+parses
+x : int, y : float;
+^^this^^
+then recursively calls itself to parse the rest
+NOTE: this function actually parses all types in the declaration, but it just
+calls itself to do that.
+
+*/
+static bool parse_single_type_in_decl(Parser *p, Declaration *d) {
Tokenizer *t = p->tokr;
/* OPTIM: Maybe don't use a dynamic array or use parser allocator. */
- d->where = t->token->where;
- arr_create(&d->idents, sizeof(Identifier));
-
- d->flags = 0;
-
+ size_t n_idents_with_this_type = 1;
while (1) {
Identifier *ident = arr_add(&d->idents);
if (t->token->kind != TOKEN_IDENT) {
@@ -914,6 +931,7 @@ static bool decl_parse(Declaration *d, Parser *p) {
t->token++;
if (token_is_kw(t->token, KW_COMMA)) {
t->token++;
+ n_idents_with_this_type++;
continue;
}
if (token_is_kw(t->token, KW_COLON)) {
@@ -935,15 +953,50 @@ static bool decl_parse(Declaration *d, Parser *p) {
tokr_err(t, "Cannot infer type without expression.");
return false;
}
-
- if (!token_is_kw(t->token, KW_EQ)) {
+
+ bool annotates_type = !token_is_kw(t->token, KW_EQ) && !token_is_kw(t->token, KW_COMMA);
+ if (d->type.kind != TYPE_VOID /* multiple types in one declaration */
+ && (!!(d->flags & DECL_FLAG_ANNOTATES_TYPE)) != annotates_type) { /* annotation on one decl but not the other */
+ /* e.g. x: int, y := 3, 5;*/
+ tokr_err(t, "You must specify either all types or no types in a single declaration.");
+ return false;
+ }
+ printf("%lu\n",n_idents_with_this_type);
+ if (annotates_type) {
d->flags |= DECL_FLAG_ANNOTATES_TYPE;
- if (!parse_type(p, &d->type)) {
+ Type type;
+ if (!parse_type(p, &type)) {
return false;
}
+ if (n_idents_with_this_type == 1 && d->type.kind == TYPE_VOID) {
+ d->type = type;
+ } else if (d->type.kind == TYPE_TUPLE) {
+ /* add to tuple */
+ for (size_t i = 0; i < n_idents_with_this_type; i++) {
+ *(Type*)arr_add(&d->type.tuple) = type;
+ }
+ } else {
+ /* construct tuple */
+ Array tup_arr;
+ arr_create(&tup_arr, sizeof(Type));
+ if (d->type.kind != TYPE_VOID) {
+ *(Type*)arr_add(&tup_arr) = d->type; /* add current type */
+ }
+ d->type.kind = TYPE_TUPLE;
+ d->type.tuple = tup_arr;
+ for (size_t i = 0; i < n_idents_with_this_type; i++) {
+ *(Type*)arr_add(&d->type.tuple) = type;
+ }
+ }
}
- /* OPTIM: switch */
+ if (token_is_kw(t->token, KW_COMMA)) {
+ /* next type in declaration */
+ t->token++; /* move past , */
+ return parse_single_type_in_decl(p, d);
+ }
+
+ /* OPTIM: switch t->token->kw ? */
if (token_is_kw(t->token, KW_EQ)) {
t->token++;
if (!parse_expr(p, &d->expr, expr_find_end(p, EXPR_END_SEMICOLON)))
@@ -964,6 +1017,15 @@ static bool decl_parse(Declaration *d, Parser *p) {
}
}
+static bool parse_decl(Parser *p, Declaration *d) {
+ d->type.kind = TYPE_VOID;
+ d->where = p->tokr->token->where;
+ arr_create(&d->idents, sizeof(Identifier));
+
+ d->flags = 0;
+ return parse_single_type_in_decl(p, d); /* recursively calls itself to parse all types */
+}
+
static bool parse_stmt(Parser *p, Statement *s) {
Tokenizer *t = p->tokr;
if (t->token->kind == TOKEN_EOF)
@@ -976,7 +1038,7 @@ static bool parse_stmt(Parser *p, Statement *s) {
if (token_is_kw(t->token + 1, KW_COLON) || token_is_kw(t->token + 1, KW_COMMA)
|| token_is_kw(t->token + 1, KW_AT)) {
s->kind = STMT_DECL;
- if (!decl_parse(&s->decl, p)) {
+ if (!parse_decl(p, &s->decl)) {
/* move to next statement */
/* TODO: This might cause unhelpful errors if the first semicolon is inside a block, etc. */
while (!token_is_kw(t->token, KW_SEMICOLON)) {
@@ -1053,6 +1115,16 @@ static void fprint_type(FILE *out, Type *t) {
fprintf(out, ") ");
fprint_type(out, &types[0]);
} break;
+ case TYPE_TUPLE: {
+ fprintf(out, "(");
+ arr_foreach(&t->tuple, Type, child) {
+ if (child != t->tuple.data) {
+ fprintf(out, ", ");
+ }
+ fprint_type(out, child);
+ }
+ fprintf(out, ")");
+ } break;
case TYPE_ARR:
fprintf(out, "[");
if (t->flags & TYPE_FLAG_RESOLVED) {
diff --git a/test.toc b/test.toc
index 4f7056e..0138c1e 100644
--- a/test.toc
+++ b/test.toc
@@ -1,16 +1,5 @@
main @= fn() {
- bar : [3]fn();
- foo := fn() {};
- bar[1] = foo;
- bar[2] = foo;
- bar[0] = foo;
- i := 0;
- x := bar[i];
- x();
- i = i + 1;
- x = bar[i];
- x();
- i = i + 1;
- x = bar[i];
- x();
+ foo , bar, basdf, asdf,ksdja ,dfa : int, kasjdfk, dasfjkfha , sdf, sad : fn() = 3;
+ x,y,z:int=3,3,3;
+ abc := bar;
};
diff --git a/types.c b/types.c
index bd908b0..7278d02 100644
--- a/types.c
+++ b/types.c
@@ -41,7 +41,6 @@ static bool block_exit(Block *b) {
if (last_decl->scope == b) {
arr_remove_last(decls); /* remove that declaration */
}
-
}
}
}
@@ -78,6 +77,14 @@ static bool type_eq(Type *a, Type *b) {
}
return true;
}
+ case TYPE_TUPLE:
+ if (a->tuple.len != b->tuple.len) return false;
+ Type *a_types = a->tuple.data, *b_types = b->tuple.data;
+ for (size_t i = 0; i < a->tuple.len; i++) {
+ if (!type_eq(&a_types[i], &b_types[i]))
+ return false;
+ }
+ return true;
case TYPE_ARR:
if (a->arr.n != b->arr.n) return false;
return type_eq(a->arr.of, b->arr.of);
@@ -369,6 +376,11 @@ static bool types_decl(Declaration *d) {
if (!type_must_eq(d->expr.where, &d->type, &d->expr.type))
return false;
} else {
+ if (d->expr.type.kind == TYPE_VOID) {
+ /* e.g. x := (fn(){})(); */
+ err_print(d->expr.where, "Used return value of function which does not return anything.");
+ return false;
+ }
d->type = d->expr.type;
}
}