diff options
-rw-r--r-- | copy.c | 33 | ||||
-rw-r--r-- | identifiers.c | 22 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 183 | ||||
-rw-r--r-- | types.h | 49 |
5 files changed, 101 insertions, 190 deletions
@@ -275,38 +275,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { copy_block(c, &wout->body, &win->body, 0); } break; case EXPR_FOR: { - ForExpr *fin = in->for_; - ForExpr *fout = allocr_malloc(a, sizeof *fout); - out->for_ = fout; - *fout = *fin; - - Block *prev = c->block; - idents_create(&fout->body.idents, c->allocr, &fout->body); - c->block = &fout->body; - - if (fout->index) { - copier_ident_translate(c, &fout->index); - fout->index->decl_kind = IDECL_FOR; - fout->index->decl_for = fout; - } - if (fout->value) { - copier_ident_translate(c, &fout->value); - fout->value->decl_kind = IDECL_FOR; - fout->value->decl_for = fout; - } - if (fin->flags & FOR_ANNOTATED_TYPE) - copy_type(c, &fout->type, &fin->type); - if (fin->flags & FOR_IS_RANGE) { - fout->range.from = copy_expr_(c, fin->range.from); - if (fin->range.to) - fout->range.to = copy_expr_(c, fin->range.to); - if (fin->range.step) - fout->range.step = copy_expr_(c, fin->range.step); - } else { - fout->of = copy_expr_(c, fin->of); - } - c->block = prev; - copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS); + /* TODO */ } break; case EXPR_FN: copy_fn_expr(c, out->fn = allocr_malloc(a, sizeof *out->fn), in->fn, 0); diff --git a/identifiers.c b/identifiers.c index b5e3f46..bb30e36 100644 --- a/identifiers.c +++ b/identifiers.c @@ -211,27 +211,11 @@ static int ident_index_in_decl(Identifier i, Declaration *d) { return -1; } -static Location ident_decl_location(File *file, Identifier i) { - switch (i->decl_kind) { - case IDECL_DECL: - return i->decl->where; - case IDECL_FOR: - if (i == i->decl_for->index) { - return token_location(file, i->decl_for->index_token); - } else { - assert(i == i->decl_for->value); - return token_location(file, i->decl_for->value_token); - } - break; - case IDECL_NONE: - break; - } - assert(0); - Location l = {0}; - return l; +static Location ident_decl_location(Identifier i) { + return i->decl->where; } static bool ident_is_declared(Identifier i) { - return i && i->decl_kind != IDECL_NONE; + return i && i->decl; } @@ -8,12 +8,13 @@ /* TODO: +replace weird EXPR_FOR system with just a declaration- would make "for use p := points" easier + -> rewrite for copying EXPR_IDENT should be a string before typing, also struct member accesses use - use with struct members (e.g. SuperPoint ::= struct { use p: Point; }) local structs should not be named in C simplify eval macros with val_to_u/i64 -consider replacing weird EXPR_FOR system with just a declaration- would make "for use p := points" easier &&, || start making a standard library... (printf; stringbuilder would be nice to have) switch @@ -32,6 +33,7 @@ make sure that floating point literals are exact as possible have them be in std/math.toc) once you have a bunch of test code, try making more Expression members pointers error on x ::= {return; 3} +struct param inference maybe macros are just inline functions #returns_code (struct body is a block, to be evaluated at compile time, which returns the actual statements) - struct varargs @@ -6,20 +6,25 @@ static Status parse_expr(Parser *p, Expression *e, Token *end); static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement); enum { - PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR = 0x01, - PARSE_DECL_ALLOW_SEMI_CONST = 0x02, - PARSE_DECL_ALLOW_INFER = 0x04, - PARSE_DECL_ALLOW_EXPORT = 0x08, - PARSE_DECL_DONT_SET_IDECLS = 0x10 + PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR = 0x0001, + PARSE_DECL_ALLOW_SEMI_CONST = 0x0002, + PARSE_DECL_ALLOW_INFER = 0x0004, + PARSE_DECL_ALLOW_EXPORT = 0x0008, + PARSE_DECL_DONT_SET_IDECLS = 0x0010, + PARSE_DECL_IGNORE_EXPR = 0x0020, /* NOTE: if you pass this to parse_decl, you must set d->where.end */ + DECL_CAN_END_WITH_SEMICOLON = 0x0100, + DECL_CAN_END_WITH_RPAREN = 0x0200, + DECL_CAN_END_WITH_LBRACE = 0x0400, + DECL_CAN_END_WITH_COMMA = 0x0800 }; -static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 flags); -static Status parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end); +static Status parse_decl(Parser *p, Declaration *d, U16 flags); +static Status parse_decl_list(Parser *p, Declaration **decls, U16 flags); enum { PARSE_BLOCK_DONT_CREATE_IDENTS = 0x01 }; static bool parse_block(Parser *p, Block *b, U8 flags); static bool is_decl(Tokenizer *t); -static inline bool ends_decl(Token *t, DeclEndKind ends_with); +static inline bool ends_decl(Token *t, U16 flags); static bool fn_has_any_const_params(FnExpr *f) { arr_foreach(f->params, Declaration, param) @@ -605,7 +610,8 @@ static Status parse_type(Parser *p, Type *type, Location *where) { tokr_err(t, "Empty struct parameter lists are not allowed."); goto struct_fail; } - if (!parse_decl_list(p, &struc->params, DECL_END_RPAREN_COMMA)) + if (!parse_decl_list(p, &struc->params, DECL_CAN_END_WITH_RPAREN | DECL_CAN_END_WITH_COMMA | + PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) goto struct_fail; arr_foreach(struc->params, Declaration, param) { @@ -618,11 +624,6 @@ static Status parse_type(Parser *p, Type *type, Location *where) { err_print(param->where, "structs cannot have varargs parameters (yet)."); goto struct_fail; } - if (param->flags & DECL_INFER) { - /* TODO(eventually) */ - err_print(param->where, "Struct parameters cannot be inferred (yet)."); - goto struct_fail; - } param->flags |= DECL_IS_PARAM; } } @@ -847,7 +848,7 @@ static Status parse_block(Parser *p, Block *b, U8 flags) { } /* does NOT handle empty declaration lists */ -static Status parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end) { +static Status parse_decl_list(Parser *p, Declaration **decls, U16 flags) { Tokenizer *t = p->tokr; bool ret = true; bool first = true; @@ -858,10 +859,10 @@ static Status parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_e !token_is_kw(t->token - 1, KW_LBRACE)))) { first = false; Declaration *decl = parser_arr_add(p, decls); - if (!parse_decl(p, decl, decl_end, PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR | PARSE_DECL_ALLOW_SEMI_CONST | PARSE_DECL_ALLOW_INFER)) { + if (!parse_decl(p, decl, flags)) { ret = false; /* skip to end of list */ - while (t->token->kind != TOKEN_EOF && !ends_decl(t->token, decl_end)) + while (t->token->kind != TOKEN_EOF && !ends_decl(t->token, flags)) ++t->token; break; } @@ -904,7 +905,9 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) { if (token_is_kw(t->token, KW_RPAREN)) { ++t->token; } else { - if (!parse_decl_list(p, &f->params, DECL_END_RPAREN_COMMA)) + if (!parse_decl_list(p, &f->params, DECL_CAN_END_WITH_RPAREN + | DECL_CAN_END_WITH_COMMA | PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR + | PARSE_DECL_ALLOW_SEMI_CONST | PARSE_DECL_ALLOW_INFER)) return false; arr_foreach(f->params, Declaration, param) { param->flags |= DECL_IS_PARAM; @@ -921,17 +924,13 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) { f->ret_type.kind = TYPE_VOID; f->ret_type.flags = 0; } else if (is_decl(t)) { - if (!parse_decl_list(p, &f->ret_decls, DECL_END_LBRACE_COMMA)) + if (!parse_decl_list(p, &f->ret_decls, DECL_CAN_END_WITH_LBRACE | DECL_CAN_END_WITH_COMMA)) return false; arr_foreach(f->ret_decls, Declaration, d) { - if ((d->flags & DECL_IS_CONST) || (d->flags & DECL_SEMI_CONST)) { + if (d->flags & DECL_IS_CONST) { err_print(d->where, "Named return values cannot be constant."); success = false; goto ret; } - if (d->flags & DECL_INFER) { - err_print(d->where, "Can't infer the value of a named return value!"); - success = false; goto ret; - } } --t->token; /* move back to { */ /* just set return type to void. the actual return type will be set by types.c:type_of_fn */ @@ -1006,7 +1005,7 @@ static Status check_ident_redecl(Parser *p, Identifier i) { if (i->decl_kind != IDECL_NONE) { /* declared */ char *s = ident_to_str(i); tokr_err(t, "Redeclaration of identifier %s.", s); - info_print(ident_decl_location(p->file, i), "Previous declaration was here."); + info_print(ident_decl_location(i), "Previous declaration was here."); free(s); return false; } @@ -1386,71 +1385,20 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { case KW_FOR: { e->kind = EXPR_FOR; ForExpr *fo = e->for_ = parser_malloc(p, sizeof *fo); - fo->val_stack = NULL; fo->flags = 0; - fo->value = NULL; - fo->index = NULL; + fo->type = NULL; Block *prev_block = p->block; fo->body.parent = p->block; p->block = &fo->body; idents_create(&p->block->idents, p->allocr, p->block); ++t->token; - if (token_is_kw(t->token, KW_COLON) - || (t->token->kind == TOKEN_IDENT - && (token_is_kw(t->token + 1, KW_COLON) - || (token_is_kw(t->token + 1, KW_COMMA) - && t->token[2].kind == TOKEN_IDENT - && token_is_kw(t->token + 3, KW_COLON))))) { - if (t->token->kind == TOKEN_IDENT) { - fo->value = parser_ident_insert(p, t->token->ident); - if (!check_ident_redecl(p, fo->value)) - goto for_fail; - if (ident_eq_str(fo->value, "_")) { /* ignore value */ - fo->value = NULL; - } else { - fo->value->decl_kind = IDECL_FOR; - fo->value->decl_for = fo; - } - ++t->token; - if (token_is_kw(t->token, KW_COMMA)) { - ++t->token; - if (t->token->kind == TOKEN_IDENT) { - fo->index = parser_ident_insert(p, t->token->ident); - if (!check_ident_redecl(p, fo->index)) - goto for_fail; - if (ident_eq_str(fo->index, "_")) { /* ignore index */ - fo->index = NULL; - } else { - fo->index->decl_kind = IDECL_FOR; - fo->index->decl_for = fo; - } - ++t->token; - } else { - tokr_err(t, "Expected identifier after , in for loop."); - goto for_fail; - } - } - } - if (!token_is_kw(t->token, KW_COLON)) { - tokr_err(t, "Expected : following identifiers in for loop."); - goto for_fail; - } - ++t->token; - if (token_is_kw(t->token, KW_COLON)) { - tokr_err(t, "The variable(s) in a for loop cannot be constant."); - goto for_fail; - } - if (!token_is_kw(t->token, KW_EQ)) { - fo->flags |= FOR_ANNOTATED_TYPE; - if (!parse_type(p, &fo->type, NULL)) - goto for_fail; - if (!token_is_kw(t->token, KW_EQ)) { - tokr_err(t, "Expected = in for statement."); - goto for_fail; - } - } - ++t->token; + if (!parse_decl(p, &fo->header, PARSE_DECL_IGNORE_EXPR | DECL_CAN_END_WITH_LBRACE)) + goto for_fail; + if (!token_is_kw(t->token, KW_EQ)) { + tokr_err(t, "Expected = to follow for declaration."); + goto for_fail; } + ++t->token; Token *first_end; first_end = expr_find_end(p, EXPR_CAN_END_WITH_COMMA|EXPR_CAN_END_WITH_DOTDOT|EXPR_CAN_END_WITH_LBRACE); Expression *first; first = parser_new_expr(p); if (!parse_expr(p, first, first_end)) @@ -2127,20 +2075,23 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { return true; } -static inline bool ends_decl(Token *t, DeclEndKind ends_with) { +static inline bool ends_decl(Token *t, U16 flags) { 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; - case DECL_END_LBRACE_COMMA: - return t->kw == KW_LBRACE || t->kw == KW_COMMA; - default: assert(0); return false; + switch (t->kw) { + case KW_SEMICOLON: + return (flags & DECL_CAN_END_WITH_SEMICOLON) != 0; + case KW_RPAREN: + return (flags & DECL_CAN_END_WITH_RPAREN) != 0; + case KW_COMMA: + return (flags & DECL_CAN_END_WITH_COMMA) != 0; + case KW_LBRACE: + return (flags & DECL_CAN_END_WITH_LBRACE) != 0; + default: break; } + return false; } -static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 flags) { +static Status parse_decl(Parser *p, Declaration *d, U16 flags) { Tokenizer *t = p->tokr; d->where = parser_mk_loc(p); d->idents = NULL; @@ -2234,17 +2185,31 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f } } { - const char *end_str = NULL; - switch (ends_with) { - case DECL_END_SEMICOLON: end_str = "';'"; break; - case DECL_END_RPAREN_COMMA: end_str = "')' or ','"; break; - case DECL_END_LBRACE_COMMA: end_str = "'{' or ','"; break; + if (flags & PARSE_DECL_IGNORE_EXPR) { + if (token_is_kw(t->token, KW_EQ)) + return true; + if (ends_decl(t->token, flags)) + return true; } - assert(end_str); - + + char end_str[32] = {0}; + if (flags & DECL_CAN_END_WITH_SEMICOLON) + strcat(end_str, "';'/"); + if (flags & DECL_CAN_END_WITH_RPAREN) + strcat(end_str, "')'/"); + if (flags & DECL_CAN_END_WITH_LBRACE) + strcat(end_str, "'{'/"); + if (flags & DECL_CAN_END_WITH_COMMA) + strcat(end_str, "','/"); + { + size_t len = strlen(end_str); + assert(len && end_str[len-1] == '/'); + end_str[len-1] = 0; + } + if (token_is_kw(t->token, KW_EQ)) { ++t->token; - if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) { + if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, flags)) { /* inferred expression */ d->flags |= DECL_INFER; if (!(d->flags & DECL_IS_CONST)) { @@ -2259,10 +2224,10 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f } else { d->flags |= DECL_HAS_EXPR; uint16_t expr_flags = 0; - if (ends_with == DECL_END_RPAREN_COMMA) + if (flags & DECL_CAN_END_WITH_COMMA) expr_flags |= EXPR_CAN_END_WITH_COMMA; - if (ends_with == DECL_END_LBRACE_COMMA) - expr_flags |= EXPR_CAN_END_WITH_LBRACE | EXPR_CAN_END_WITH_COMMA; + if (flags & DECL_CAN_END_WITH_LBRACE) + expr_flags |= EXPR_CAN_END_WITH_LBRACE; if (is_varargs) { tokr_err(t, "Default varargs are not allowed."); goto ret_false; @@ -2277,16 +2242,16 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f t->token = end; /* move to ; */ goto ret_false; } - if (ends_with == DECL_END_SEMICOLON && end > t->tokens && token_is_kw(end - 1, KW_RBRACE)) { + if ((flags & DECL_CAN_END_WITH_SEMICOLON) && end > t->tokens && token_is_kw(end - 1, KW_RBRACE)) { /* allow semicolon to be ommitted, e.g. f ::= fn() {} */ - } else if (ends_decl(t->token, ends_with)) { + } else if (ends_decl(t->token, flags)) { ++t->token; } else { tokr_err(t, "Expected %s at end of declaration.", end_str); goto ret_false; } } - } else if (ends_decl(t->token, ends_with)) { + } else if (ends_decl(t->token, flags)) { ++t->token; } else { tokr_err(t, "Expected %s or '=' at end of delaration.", end_str); @@ -2302,7 +2267,7 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f } parser_put_end(p, &d->where); - if (ends_with != DECL_END_SEMICOLON) + if (!token_is_kw(t->token, KW_SEMICOLON)) --d->where.end; /* e.g., in fn(x: float), the param decl does not contain the ) */ return true; @@ -2346,7 +2311,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { *was_a_statement = true; if (is_decl(t)) { s->kind = STMT_DECL; - if (!parse_decl(p, s->decl = parser_malloc(p, sizeof *s->decl), DECL_END_SEMICOLON, PARSE_DECL_ALLOW_EXPORT)) { + if (!parse_decl(p, s->decl = parser_malloc(p, sizeof *s->decl), DECL_CAN_END_WITH_SEMICOLON | PARSE_DECL_ALLOW_EXPORT)) { return false; } } else if (t->token->kind == TOKEN_KW) { @@ -638,28 +638,6 @@ enum { FOR_ANNOTATED_TYPE = 0x02, }; -typedef struct ForExpr { - U8 flags; - Type type; /* uninitialized unless typed or flags & FOR_ANNOTATED_TYPE */ - Identifier index; /* NULL = no index */ - Identifier value; /* NULL = no value */ - Token *index_token, *value_token; /* used for errors */ - Block body; - union { - struct { - struct Expression *from; /* can't be null */ - struct Expression *to; /* can be null */ - union { - /* (either) can be null */ - struct Expression *step; /* before typing */ - Value *stepval; /* after typing */ - }; - } range; - struct Expression *of; - }; - Value **val_stack; /* see Declaration for comments */ -} ForExpr; - enum { FN_EXPR_FOREIGN = 0x01, @@ -850,7 +828,7 @@ typedef struct Expression { } del; IfExpr *if_; WhileExpr *while_; - ForExpr *for_; + struct ForExpr *for_; FnExpr *fn; CastExpr cast; SliceExpr slice; @@ -913,6 +891,25 @@ typedef struct Declaration { } Declaration; typedef Declaration *DeclarationPtr; +typedef struct ForExpr { + U8 flags; + Type *type; /* NULL before typing */ + Declaration header; + Block body; + union { + struct { + struct Expression *from; /* can't be null */ + struct Expression *to; /* can be null */ + union { + /* (either) can be null */ + struct Expression *step; /* before typing */ + Value *stepval; /* after typing */ + }; + } range; + struct Expression *of; + }; +} ForExpr; + typedef enum { STMT_DECL, STMT_EXPR, @@ -1012,12 +1009,6 @@ typedef struct Parser { ParsedFile *parsed_file; } Parser; -typedef enum { - DECL_END_SEMICOLON, - DECL_END_RPAREN_COMMA, - DECL_END_LBRACE_COMMA -} DeclEndKind; - #if COMPILE_TIME_FOREIGN_FN_SUPPORT typedef struct { void *handle; |