diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-08-30 16:13:59 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-08-30 16:13:59 -0400 |
commit | 94e8da0bc35d80df12e2d1490b3aa751576095f6 (patch) | |
tree | ebeba71ab0a68b241319fb2a9e1e5854b36d386c | |
parent | 1929fee97726344c0e83d74258ff27d0488770f9 (diff) |
Added tuple types
-rw-r--r-- | base_cgen.c | 6 | ||||
-rw-r--r-- | cgen.c | 3 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | out.c | 19 | ||||
-rw-r--r-- | parse.c | 94 | ||||
-rw-r--r-- | test.toc | 17 | ||||
-rw-r--r-- | types.c | 14 |
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); @@ -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"); @@ -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" @@ -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) { @@ -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) { @@ -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; }; @@ -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; } } |