diff options
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | parse.c | 20 | ||||
-rw-r--r-- | test.toc | 11 | ||||
-rw-r--r-- | types.c | 36 |
4 files changed, 42 insertions, 27 deletions
@@ -1,5 +1,7 @@ /* TODO: +get rid of multiple types in one decl (no a, b := twofn();) +casting re-do cgen */ #include "toc.c" @@ -1371,15 +1371,26 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndType ends_with, uint16_ return ret; } +static bool is_decl(Tokenizer *t) { + Token *token = t->token; + while (1) { + if (token->kind != TOKEN_IDENT) return false; + token++; + if (token->kind != TOKEN_KW) return false; + if (token->kw == KW_COLON || token->kw == KW_AT) + return true; + if (token->kw != KW_COMMA) return false; + token++; + } +} + static bool parse_stmt(Parser *p, Statement *s) { Tokenizer *t = p->tokr; s->flags = 0; if (t->token->kind == TOKEN_EOF) tokr_err(t, "Expected statement."); s->where = t->token->where; - /* - TODO: statements such as 3, 5; will not work. - */ + if (token_is_kw(t->token, KW_RETURN)) { s->kind = STMT_RET; t->token++; @@ -1404,8 +1415,7 @@ static bool parse_stmt(Parser *p, Statement *s) { t->token = end + 1; return success; } - 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)) { + if (is_decl(t)) { s->kind = STMT_DECL; if (!parse_decl(p, &s->decl, DECL_END_SEMICOLON, 0)) { return false; @@ -1,11 +1,8 @@ main @= fn() { - //foo @= fn(x: int) { return; }; // b := !(5 > 3 && 4 <= 3 && 3 >= 2 || 0 == 1 || 5 != 3); - b := !(5 < 3); - a := (5 == 3); - C @= 3 != 4; - //x @= !!!!!!!false; - -// foo := 5 < 3; + foo : [3]int; + // x, foo[0], foo[1] = 3, 5; + x :, y := 0; + x = 3.5; }; @@ -146,7 +146,13 @@ static bool expr_must_lval(Expression *e) { if (e->unary.op == UNARY_DEREF) return true; break; case EXPR_BINARY_OP: - if (e->binary.op == BINARY_AT_INDEX) return true; + switch (e->binary.op) { + case BINARY_AT_INDEX: return true; + case BINARY_COMMA: + /* x, y is an lval, but 3, "hello" is not. */ + return expr_must_lval(e->binary.lhs) && expr_must_lval(e->binary.rhs); + default: break; + } break; default: break; @@ -218,13 +224,13 @@ 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) { - long index = (long)(decl_i - (Identifier*)d->idents.data); *t = ((Type*)d->type.tuple.data)[index]; return true; } + index++; } assert(0); return false; @@ -238,10 +244,12 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { if (!type_of_fn(tr, d->expr.fn, t)) return false; return true; } else { - char *s = ident_to_str(i); - err_print(where, "Use of identifier %s before its declaration.\nNote that it is only possible to use a constant function before it is directly declared (e.g. x @= fn() {}).", s); - info_print(d->where, "%s will be declared here.", s); - free(s); + if (location_after(d->where, where)) { + char *s = ident_to_str(i); + err_print(where, "Use of identifier %s before its declaration.\nNote that it is only possible to use a constant function before it is directly declared (e.g. x @= fn() {}).", s); + info_print(d->where, "%s will be declared here.", s); + free(s); + } /* else, there should have been an error earlier */ return false; } } @@ -599,6 +607,7 @@ static bool types_expr(Typer *tr, Expression *e) { match = false; } } + if (!type_eq(lhs_type, rhs_type)) match = false; if (match) { switch (e->binary.op) { case BINARY_SET: @@ -623,14 +632,10 @@ static bool types_expr(Typer *tr, Expression *e) { /* promote to float */ t->builtin = BUILTIN_F32; } - } else if (type_eq(lhs_type, rhs_type)) { - if (!lhs_is_flexible) - *t = *lhs_type; - else - *t = *rhs_type; - } else { - match = false; - } + } else if (!lhs_is_flexible) + *t = *lhs_type; + else + *t = *rhs_type; } break; } } @@ -737,6 +742,7 @@ static bool types_decl(Typer *tr, Declaration *d) { goto ret; } d->type = d->expr.type; + d->type.flags &= ~TYPE_FLAG_FLEXIBLE; /* x := 5; => x is not flexible */ } if (d->flags & DECL_FLAG_CONST) { if (!d->val) { |