diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-26 18:44:59 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-26 18:44:59 -0400 |
commit | 8b31f7583aa6fc1853a0124077e704a58998e82a (patch) | |
tree | ffd103797af492fabf4e659017a8daf04f770da2 | |
parent | b2ec9e753e74e57cd0d140c2608a82169253943c (diff) |
started newtype
-rw-r--r-- | abbrevs.txt | 1 | ||||
-rw-r--r-- | cgen.c | 9 | ||||
-rw-r--r-- | parse.c | 79 | ||||
-rw-r--r-- | test.toc | 20 | ||||
-rw-r--r-- | tokenizer.c | 23 | ||||
-rw-r--r-- | types.h | 12 |
6 files changed, 90 insertions, 54 deletions
diff --git a/abbrevs.txt b/abbrevs.txt index d694268..1075c21 100644 --- a/abbrevs.txt +++ b/abbrevs.txt @@ -20,5 +20,6 @@ ptr - pointer ret - return stmt - statement str - string +tdecl - type declaration tokr - tokenizer val - value @@ -1260,6 +1260,15 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { cgen_write(g, ";"); cgen_nl(g); break; + case STMT_TDECL: + cgen_write(g, "typedef "); + if (!cgen_type_pre(g, &s->tdecl.type, s->where)) return false; + cgen_write(g, " "); + cgen_ident(g, s->tdecl.name); + if (!cgen_type_post(g, &s->tdecl.type, s->where)) return false; + cgen_write(g, ";"); + cgen_nl(g); + break; case STMT_RET: if (!cgen_ret(g, s->ret.flags & RET_FLAG_EXPR ? &s->ret.expr : NULL)) return false; @@ -1,5 +1,5 @@ static bool parse_expr(Parser *p, Expression *e, Token *end); - +static bool parse_stmt(Parser *p, Statement *s); #define PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR 0x01 static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_t flags); @@ -237,7 +237,7 @@ static inline Expression *parser_new_expr(Parser *p) { #define EXPR_CAN_END_WITH_LBRACE 0x02 #define EXPR_CAN_END_WITH_COLON 0x04 /* is_vbs can be NULL */ -static Token *expr_find_end(Parser *p, uint16_t flags, bool *is_vbs) { +static Token *expr_find_end(Parser *p, U16 flags, bool *is_vbs) { Tokenizer *t = p->tokr; int paren_level = 0; int brace_level = 0; @@ -459,7 +459,6 @@ static bool parse_type(Parser *p, Type *type) { } -static bool parse_stmt(Parser *p, Statement *s); static bool parse_block(Parser *p, Block *b) { b->flags = 0; @@ -1304,7 +1303,6 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_ Tokenizer *t = p->tokr; d->flags = 0; - /* OPTIM: Maybe don't use a dynamic array or use parser allocator. */ while (1) { Identifier *ident = parser_arr_add(p, &d->idents); if (t->token->kind != TOKEN_IDENT) { @@ -1391,12 +1389,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_ ret_false: /* 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 ; */ - } + tokr_skip_semicolon(t); return false; } @@ -1419,30 +1412,46 @@ static bool parse_stmt(Parser *p, Statement *s) { if (t->token->kind == TOKEN_EOF) tokr_err(t, "Expected statement."); s->where = t->token->where; - - if (token_is_kw(t->token, KW_RETURN)) { - s->kind = STMT_RET; - t->token++; - s->ret.flags = 0; - if (token_is_kw(t->token, KW_SEMICOLON)) { - /* return with no expr */ + if (t->token->kind == TOKEN_KW) { + switch (t->token->kw) { + case KW_RETURN: { + s->kind = STMT_RET; t->token++; - return true; - } - s->ret.flags |= RET_FLAG_EXPR; - Token *end = expr_find_end(p, 0, NULL); - if (!end) { - while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */ - return false; + s->ret.flags = 0; + if (token_is_kw(t->token, KW_SEMICOLON)) { + /* return with no expr */ + t->token++; + return true; + } + s->ret.flags |= RET_FLAG_EXPR; + Token *end = expr_find_end(p, 0, NULL); + if (!end) { + while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */ + return false; + } + if (!token_is_kw(end, KW_SEMICOLON)) { + err_print(end->where, "Expected ';' at end of return statement."); + t->token = end->kind == TOKEN_EOF ? end : end + 1; + return false; + } + bool success = parse_expr(p, &s->ret.expr, end); + t->token = end + 1; + return success; } - if (!token_is_kw(end, KW_SEMICOLON)) { - err_print(end->where, "Expected ';' at end of return statement."); - t->token = end->kind == TOKEN_EOF ? end : end + 1; - return false; + case KW_NEWTYPE: + s->kind = STMT_TDECL; + t->token++; + if (t->token->kind != TOKEN_IDENT) { + tokr_err(t, "Expected identifier after \"newtype\"."); + tokr_skip_semicolon(t); + } + s->tdecl.name = t->token->ident; + t->token++; + if (!parse_type(p, &s->tdecl.type)) + return false; + return true; + default: break; } - bool success = parse_expr(p, &s->ret.expr, end); - t->token = end + 1; - return success; } if (is_decl(t)) { s->kind = STMT_DECL; @@ -1695,9 +1704,7 @@ static void fprint_stmt(FILE *out, Statement *s) { PARSE_PRINT_LOCATION(s->where); if (s->flags & STMT_FLAG_VOIDED_EXPR) fprintf(out, "(void)"); - switch (s->kind) { - case STMT_DECL: fprint_decl(out, &s->decl); fprintf(out, ";\n"); @@ -1712,6 +1719,12 @@ static void fprint_stmt(FILE *out, Statement *s) { fprint_expr(out, &s->ret.expr); fprintf(out, ";\n"); break; + case STMT_TDECL: + fprintf(out, "newtype "); + fprint_ident(out, s->tdecl.name); + fprintf(out, " "); + fprint_type(out, &s->tdecl.type); + break; } } @@ -13,24 +13,8 @@ putf @= fn(x: float) { "); }; -foo @= fn() [3]int { - x : [3]int; - x[0] = 1; - x[1] = 2; - x[2] = 3; - x -}; - -getASDF @= fn(i: int) int { - ASDF @= foo(); - ASDF[i] -}; +newtype Foo int main @= fn() { - // ptriangle @= pascal(); - // puti(ptriangle[49][25]); - puti(getASDF(2)); - puti(getASDF(1)); - puti(getASDF(0)); - + // x : Foo; }; diff --git a/tokenizer.c b/tokenizer.c index 2e6bb4d..315379d 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -3,7 +3,7 @@ static const char *keywords[KW_COUNT] = "+", "-", "*", "!", "&", "/", "=", "if", "elif", "else", "while", "return", "fn", "as", - "new", "del", + "new", "del", "newtype", "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "float", "f32", "f64", "char", "bool", "true", "false"}; @@ -490,6 +490,27 @@ static bool tokenize_string(Tokenizer *t, char *str) { return !has_err; } +/* + skip to one token past the next semicolon not in braces (or the end of the file). +*/ +static void tokr_skip_semicolon(Tokenizer *t) { + int brace_level = 0; + while (t->token->kind != TOKEN_EOF) { + if (t->token->kind == TOKEN_KW) switch (t->token->kw) { + case KW_LBRACE: brace_level++; break; + case KW_RBRACE: brace_level--; break; + case KW_SEMICOLON: + if (brace_level == 0) { + t->token++; + return; + } + break; + default: break; + } + t->token++; + } +} + /* ONLY frees tokens, not string literals. You can call this followed by tokr_free. */ static void tokr_free_tokens(Tokenizer *t) { arr_clear(&t->tokens); @@ -169,6 +169,7 @@ typedef enum { KW_AS, KW_NEW, KW_DEL, + KW_NEWTYPE, KW_INT, KW_I8, KW_I16, @@ -470,7 +471,8 @@ typedef struct Declaration { typedef enum { STMT_DECL, STMT_EXPR, - STMT_RET + STMT_RET, + STMT_TDECL } StatementKind; #define RET_FLAG_EXPR 0x01 @@ -479,12 +481,18 @@ typedef struct { Expression expr; } Return; +typedef struct { + Identifier name; + Type type; +} TypeDecl; + #define STMT_FLAG_VOIDED_EXPR 0x01 /* the "4;" in fn () { 4; } is a voided expression, but the "4" in fn () int { 4 } is not */ typedef struct Statement { Location where; StatementKind kind; - unsigned short flags; + U16 flags; union { + TypeDecl tdecl; Declaration decl; Expression expr; Return ret; |