diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-09-27 14:01:53 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-09-27 14:01:53 -0400 |
commit | 191ba8c6b087c8122ab80801ac0b79caa7c9df6d (patch) | |
tree | 7a9aefc066b83df9e565ab0dcd238e987e14a6f9 | |
parent | a62657ea9888ebcc83c662ccc4528a7c95e5bed4 (diff) |
removed multiple types in one decl (fixes bugs and is probably better)
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | parse.c | 253 | ||||
-rw-r--r-- | test.toc | 8 | ||||
-rw-r--r-- | types.c | 48 |
4 files changed, 119 insertions, 192 deletions
@@ -193,7 +193,7 @@ static bool eval_expr(Expression *e, Value *v) { return true; } break; case EXPR_FN: - v->fn = *e->fn; + v->fn = e->fn; return true; case EXPR_IF: case EXPR_WHILE: { @@ -121,6 +121,12 @@ typedef struct { Block body; } WhileExpr; +typedef struct FnExpr { + Array params; /* declarations of the parameters to this function */ + Type ret_type; + Block body; +} FnExpr; /* an expression such as fn(x: int) int { 2 * x } */ + #define EXPR_FLAG_FOUND_TYPE 0x01 typedef struct Expression { @@ -147,7 +153,7 @@ typedef struct Expression { Identifier ident; IfExpr if_; WhileExpr while_; - struct FnExpr *fn; + FnExpr fn; Block block; }; } Expression; @@ -168,12 +174,6 @@ typedef struct Declaration { struct Value *val; /* only for constant decls. set to NULL here, and to actual value by types.c. */ } Declaration; -typedef struct FnExpr { - Declaration params; /* declaration of the parameters to this function */ - Type ret_type; - Block body; -} FnExpr; /* an expression such as fn(x: int) int { 2 * x } */ - typedef enum { STMT_DECL, STMT_EXPR, @@ -210,7 +210,7 @@ typedef struct { typedef enum { DECL_END_SEMICOLON, - DECL_END_RPAREN + DECL_END_RPAREN_COMMA } DeclEndType; static bool parse_expr(Parser *p, Expression *e, Token *end); @@ -678,21 +678,27 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { return false; } t->token++; - parse_decl(p, &f->params, DECL_END_RPAREN, PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR); - + arr_create(&f->params, sizeof(Declaration)); + bool ret = true; + while (!token_is_kw(t->token, KW_RPAREN)) { + Declaration *decl = arr_add(&f->params); + if (!parse_decl(p, decl, DECL_END_RPAREN_COMMA, PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) + ret = false; + } + t->token++; 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; + ret = false; } } if (!parse_block(p, &f->body)) - return false; + ret = false; f->body.flags |= BLOCK_FLAG_FN; - return true; + return ret; } /* parses, e.g. "(3, 5, foo)" */ @@ -787,8 +793,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_FN: { /* this is a function */ e->kind = EXPR_FN; - e->fn = err_malloc(sizeof *e->fn); - if (!parse_fn_expr(p, e->fn)) + if (!parse_fn_expr(p, &e->fn)) return false; if (t->token != end) { @@ -975,7 +980,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { /* can't call at start, e.g. in (fn() {})(), it is not the empty function "" being called with fn() {} as an argument - */ + */ if (token_is_kw(t->token, KW_LPAREN)) { paren_level++; token++; @@ -1198,177 +1203,111 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { return true; } -/* -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 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); + if (t->kind != TOKEN_KW) return false; + switch (ends_with) { + case DECL_END_SEMICOLON: + return t->kw == KW_SEMICOLON; + case DECL_END_RPAREN_COMMA: + return t->kw == KW_RPAREN || t->kw == KW_COMMA; + default: assert(0); return false; + } } static bool parse_decl(Parser *p, Declaration *d, DeclEndType ends_with, uint16_t flags) { d->val = NULL; - d->type.kind = TYPE_VOID; d->where = p->tokr->token->where; arr_create(&d->idents, sizeof(Identifier)); Tokenizer *t = p->tokr; d->flags = 0; - if (ends_decl(t->token, ends_with)) { - t->token++; - return true; - } /* OPTIM: Maybe don't use a dynamic array or use parser allocator. */ - size_t n_idents_with_this_type = 1; - bool ret = true; - for (size_t type_no = 0; ; type_no++) { - /* parse a single type in this decl */ - while (1) { - Identifier *ident = arr_add(&d->idents); - if (t->token->kind != TOKEN_IDENT) { - tokr_err(t, "Cannot declare non-identifier (that's a %s).", token_kind_to_str(t->token->kind)); /* TODO(eventually): an */ - ret = false; - break; - } - *ident = t->token->ident; + while (1) { + Identifier *ident = arr_add(&d->idents); + if (t->token->kind != TOKEN_IDENT) { + tokr_err(t, "Cannot declare non-identifier (%s).", token_kind_to_str(t->token->kind)); + goto ret_false; + } + *ident = t->token->ident; + t->token++; + if (token_is_kw(t->token, KW_COMMA)) { 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)) { - if (d->flags & DECL_FLAG_CONST) { - tokr_err(t, "Either everything or nothing must be constant in a declaration."); - ret = false; - break; - } - t->token++; - break; - } - if (token_is_kw(t->token, KW_AT)) { - if (type_no == 0) { - d->flags |= DECL_FLAG_CONST; - } else if (!(d->flags & DECL_FLAG_CONST)) { - tokr_err(t, "Either everything or nothing must be constant in a declaration."); - ret = false; - break; - } - t->token++; - break; - } - tokr_err(t, "Expected ',' to continue listing variables or ':' / '@' to indicate type."); - ret = false; - break; + continue; } - if (!ret) break; - - if (token_is_kw(t->token, KW_SEMICOLON) || token_is_kw(t->token, KW_RPAREN)) { - /* e.g. foo :; */ - tokr_err(t, "Cannot infer type without expression."); - ret = false; + if (token_is_kw(t->token, KW_COLON)) { + t->token++; break; } - - 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."); - ret = false; + if (token_is_kw(t->token, KW_AT)) { + d->flags |= DECL_FLAG_CONST; + t->token++; break; } - if (annotates_type) { - d->flags |= DECL_FLAG_ANNOTATES_TYPE; - Type type; - if (!parse_type(p, &type)) { - ret = false; - break; - } - 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.flags = 0; - 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; - } - } - } + tokr_err(t, "Expected ',' to continue listing variables or ':' / '@' to indicate type."); + goto ret_false; + } + + if (token_is_kw(t->token, KW_SEMICOLON) || token_is_kw(t->token, KW_RPAREN)) { + /* e.g. foo :; */ + tokr_err(t, "Cannot infer type without expression."); + goto ret_false; + } - if (token_is_kw(t->token, KW_COMMA)) { - /* next type in declaration */ - t->token++; /* move past , */ - continue; + bool annotates_type = !token_is_kw(t->token, KW_EQ) && !token_is_kw(t->token, KW_COMMA); + if (annotates_type) { + d->flags |= DECL_FLAG_ANNOTATES_TYPE; + Type type; + if (!parse_type(p, &type)) { + goto ret_false; } + d->type = type; + } - /* OPTIM: switch t->token->kw ? */ - if (token_is_kw(t->token, KW_EQ)) { - t->token++; - d->flags |= DECL_FLAG_HAS_EXPR; - Token *end = expr_find_end(p, 0, NULL); - if (!end || !token_is_kw(end, KW_SEMICOLON)) { - tokr_err(t, "Expected ';' at end of declaration."); - ret = false; - break; - } - if (!parse_expr(p, &d->expr, end)) { - t->token = end + 1; /* move past ; */ - ret = false; - break; - } - if (ends_decl(t->token, ends_with)) { - t->token++; - break; - } - tokr_err(t, "Expected '%c' at end of declaration.", - ends_with == DECL_END_SEMICOLON ? ';' : ')'); - ret = false; - } else if (ends_decl(t->token, ends_with)) { + if (token_is_kw(t->token, KW_EQ)) { + t->token++; + d->flags |= DECL_FLAG_HAS_EXPR; + Token *end = expr_find_end(p, 0, NULL); + if (!end || !token_is_kw(end, KW_SEMICOLON)) { + tokr_err(t, "Expected ';' at end of declaration."); + goto ret_false; + } + if (!parse_expr(p, &d->expr, end)) { + t->token = end; /* move to ; */ + goto ret_false; + } + if (ends_decl(t->token, ends_with)) { t->token++; } else { - tokr_err(t, "Expected '%c' or '=' at end of delaration.", + tokr_err(t, "Expected '%c' at end of declaration.", ends_with == DECL_END_SEMICOLON ? ';' : ')'); - ret = false; + goto ret_false; } - break; + } else if (ends_decl(t->token, ends_with)) { + t->token++; + } else { + tokr_err(t, "Expected '%c' or '=' at end of delaration.", + ends_with == DECL_END_SEMICOLON ? ';' : ')'); + goto ret_false; } if ((d->flags & DECL_FLAG_CONST) && !(d->flags & DECL_FLAG_HAS_EXPR) && !(flags & PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) { t->token--; /* disallowed constant without an expression, e.g. x @ int; */ tokr_err(t, "You must have an expression at the end of this constant declaration."); - ret = false; + goto ret_false; } + + return true; - if (!ret) { - /* move past end of decl */ - while (t->token->kind != TOKEN_EOF && !token_is_kw(t->token, KW_SEMICOLON)) { - t->token++; - } - if (token_is_kw(t->token, KW_SEMICOLON)) { - t->token++; /* move past ; */ - } + ret_false: + /* move past end of decl */ + while (t->token->kind != TOKEN_EOF && !token_is_kw(t->token, KW_SEMICOLON)) { + t->token++; } - return ret; + if (token_is_kw(t->token, KW_SEMICOLON)) { + t->token++; /* move past ; */ + } + return false; } static bool is_decl(Tokenizer *t) { @@ -1494,7 +1433,9 @@ static void fprint_block(FILE *out, Block *b) { static void fprint_fn_expr(FILE *out, FnExpr *f) { fprintf(out, "fn ("); - fprint_decl(out, &f->params); + arr_foreach(&f->params, Declaration, decl) { + fprint_decl(out, decl); + } fprintf(out, ") "); fprint_type(out, &f->ret_type); fprintf(out, " "); @@ -1543,7 +1484,7 @@ static void fprint_expr(FILE *out, Expression *e) { fprintf(out, ")"); break; case EXPR_FN: - fprint_fn_expr(out, e->fn); + fprint_fn_expr(out, &e->fn); break; case EXPR_IF: if (e->if_.cond) { @@ -1,8 +1,8 @@ main @= fn() { // b := !(5 > 3 && 4 <= 3 && 3 >= 2 || 0 == 1 || 5 != 3); - foo : [3]int; - // x, foo[0], foo[1] = 3, 5; - x :, y := 0; - x = 3.5; + N @= 2; + foo : [N+1]int; + x : float; + x, foo[0], foo[1] = 1.3, 3, 5; }; @@ -161,22 +161,20 @@ static bool expr_must_lval(Expression *e) { } static bool type_of_fn(Typer *tr, FnExpr *f, Type *t) { - t->kind = TYPE_FN; arr_create(&t->fn.types, sizeof(Type)); Type *ret_type = arr_add(&t->fn.types); if (!type_resolve(tr, &f->ret_type)) return false; *ret_type = f->ret_type; - Declaration *params = &f->params; - if (!types_decl(tr, params)) return false; - Type *type = ¶ms->type; - Type *param_types = type->kind == TYPE_TUPLE ? type->tuple.data : type; - for (size_t i = 0; i < params->idents.len; i++) { - Type *param_type = arr_add(&t->fn.types); - if (!type_resolve(tr, ¶m_types[i])) + arr_foreach(&f->params, Declaration, decl) { + if (!types_decl(tr, decl)) return false; + if (!type_resolve(tr, &decl->type)) return false; - *param_type = param_types[i]; + for (size_t i = 0; i < decl->idents.len; i++) { + Type *param_type = arr_add(&t->fn.types); + *param_type = decl->type; + } } return true; } @@ -222,26 +220,12 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { } if (d->flags & DECL_FLAG_FOUND_TYPE) { - if (d->idents.len > 1) { - /* it's a tuple! */ - long index = 0; - arr_foreach(&d->idents, Identifier, decl_i) { - if (*decl_i == i) { - *t = ((Type*)d->type.tuple.data)[index]; - return true; - } - index++; - } - assert(0); - return false; - } else { - *t = d->type; - return true; - } + *t = d->type; + return true; } else { if ((d->flags & DECL_FLAG_HAS_EXPR) && (d->expr.kind == EXPR_FN)) { /* allow using a function before declaring it */ - if (!type_of_fn(tr, d->expr.fn, t)) return false; + if (!type_of_fn(tr, &d->expr.fn, t)) return false; return true; } else { if (location_after(d->where, where)) { @@ -328,16 +312,18 @@ static bool types_expr(Typer *tr, Expression *e) { bool success = true; switch (e->kind) { case EXPR_FN: { - FnExpr *f = e->fn; + FnExpr *f = &e->fn; if (!type_of_fn(tr, f, t)) { success = false; goto fn_ret; } tr->ret_type = t->fn.types.data; - add_ident_decls(&f->body, &f->params); + arr_foreach(&f->params, Declaration, decl) + add_ident_decls(&f->body, decl); bool block_success = true; - block_success = types_block(tr, &e->fn->body); - remove_ident_decls(&f->body, &f->params); + block_success = types_block(tr, &e->fn.body); + arr_foreach(&f->params, Declaration, decl) + remove_ident_decls(&f->body, decl); if (!block_success) { success = false; goto fn_ret; @@ -360,7 +346,7 @@ static bool types_expr(Typer *tr, Expression *e) { goto fn_ret; } } else if (ret_type->kind != TYPE_VOID) { - Array stmts = e->fn->body.stmts; + Array stmts = e->fn.body.stmts; if (stmts.len) { Statement *last_stmt = (Statement *)stmts.data + (stmts.len - 1); if (last_stmt->kind == STMT_RET) { |