diff options
-rw-r--r-- | abbrevs.txt | 1 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | parse.c | 45 | ||||
-rw-r--r-- | test.toc | 9 | ||||
-rw-r--r-- | tokenizer.c | 3 | ||||
-rw-r--r-- | types.c | 29 |
7 files changed, 77 insertions, 19 deletions
diff --git a/abbrevs.txt b/abbrevs.txt index 56a73b7..cdf5bb1 100644 --- a/abbrevs.txt +++ b/abbrevs.txt @@ -1,5 +1,6 @@ arg - argument decl - declaration +del - delete deref - dereference direct - directive eof - end of file @@ -60,6 +60,9 @@ static bool eval_expr(Expression *e, Value *v) { *v = *ptr.points_to; return true; } break; + case UNARY_DEL: /* TODO */ + assert(0); + break; } } break; case EXPR_BINARY_OP: { @@ -197,7 +200,8 @@ static bool eval_expr(Expression *e, Value *v) { case EXPR_CALL: case EXPR_BLOCK: case EXPR_LITERAL_STR: - case EXPR_LITERAL_CHAR: { + case EXPR_LITERAL_CHAR: + case EXPR_NEW:{ err_print(e->where, "operation not supported at compile time yet."); /* TODO */ } break; case EXPR_DIRECT: @@ -1,7 +1,6 @@ /* TODO: -new/delete -evaluator (simplify compile time constant expressions) +finish evaluator re-do cgen any odd number of "s for a string */ @@ -75,6 +75,7 @@ typedef enum { EXPR_WHILE, EXPR_FN, EXPR_CAST, + EXPR_NEW, EXPR_CALL, EXPR_BLOCK, EXPR_DIRECT @@ -84,7 +85,8 @@ typedef enum { UNARY_MINUS, UNARY_ADDRESS, /* &x */ UNARY_DEREF, /* *x */ - UNARY_NOT /* !x */ + UNARY_NOT, /* !x */ + UNARY_DEL } UnaryOp; typedef enum { @@ -162,6 +164,12 @@ typedef struct Expression { CallExpr call; DirectExpr direct; Identifier ident; + struct { + Type type; + } new; + struct { + Type type; + } del; IfExpr if_; WhileExpr while_; FnExpr fn; @@ -243,6 +251,7 @@ static const char *unary_op_to_str(UnaryOp u) { case UNARY_ADDRESS: return "&"; case UNARY_DEREF: return "*"; case UNARY_NOT: return "!"; + case UNARY_DEL: return "del"; } assert(0); return ""; @@ -313,6 +322,7 @@ static BuiltinType kw_to_builtin_type(Keyword kw) { case KW_F32: return BUILTIN_F32; case KW_F64: return BUILTIN_F64; case KW_BOOL: return BUILTIN_BOOL; + case KW_CHAR: return BUILTIN_CHAR; default: return BUILTIN_TYPE_COUNT; } } @@ -389,7 +399,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { return written; } case TYPE_PTR: { - size_t written = str_copy(buffer, bufsize, "*"); + size_t written = str_copy(buffer, bufsize, "&"); written += type_to_str_(t->ptr.of, buffer + written, bufsize - written); return written; } @@ -588,11 +598,11 @@ static bool parse_type(Parser *p, Type *type) { } } break; - case KW_ASTERISK: + case KW_AMPERSAND: /* pointer */ type->kind = TYPE_PTR; type->ptr.of = err_malloc(sizeof *type->ptr.of); /* OPTIM */ - t->token++; /* move past * */ + t->token++; /* move past & */ if (!parse_type(p, type->ptr.of)) return false; break; default: @@ -792,7 +802,9 @@ static void fprint_expr(FILE *out, Expression *e); #define NOT_AN_OP -1 +/* cast/new aren't really operators since they operate on types, not exprs. */ #define CAST_PRECEDENCE 2 +#define NEW_PRECEDENCE 22 static int op_precedence(Keyword op) { switch (op) { case KW_EQ: return 0; @@ -809,6 +821,7 @@ static int op_precedence(Keyword op) { case KW_ASTERISK: return 30; case KW_SLASH: return 40; case KW_EXCLAMATION: return 50; + case KW_DEL: return 1000; default: return NOT_AN_OP; } } @@ -872,6 +885,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { return true; } + Token *start = t->token; if (t->token->kind == TOKEN_KW) switch (t->token->kw) { @@ -1012,8 +1026,12 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { break; default: { /* OPTIM: use individual cases for each op */ if (paren_level == 0 && brace_level == 0 && square_level == 0) { - int precedence = token->kw == KW_AS ? CAST_PRECEDENCE - : op_precedence(token->kw); + int precedence; + switch (token->kw) { + case KW_AS: precedence = CAST_PRECEDENCE; break; + case KW_NEW: precedence = NEW_PRECEDENCE; break; + default: precedence = op_precedence(token->kw); break; + } if (precedence == NOT_AN_OP) break; /* nvm it's not an operator */ if (lowest_precedence == NOT_AN_OP || precedence <= lowest_precedence) { lowest_precedence = precedence; @@ -1069,7 +1087,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { /* Unary */ UnaryOp op; bool is_unary = true; - switch (lowest_precedence_op->kw) { + switch (t->token->kw) { case KW_PLUS: /* unary + is ignored entirely */ t->token++; @@ -1087,6 +1105,14 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_EXCLAMATION: op = UNARY_NOT; break; + case KW_NEW: + t->token++; + e->kind = EXPR_NEW; + if (!parse_type(p, &e->new.type)) return false; + return true; + case KW_DEL: + op = UNARY_DEL; + break; default: is_unary = false; break; @@ -1161,6 +1187,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { break; case KW_AMPERSAND: case KW_EXCLAMATION: + case KW_DEL: err_print(lowest_precedence_op->where, "Unary operator '%s' being used as a binary operator!", kw_to_str(lowest_precedence_op->kw)); return false; default: assert(0); return false; @@ -1627,6 +1654,10 @@ static void fprint_expr(FILE *out, Expression *e) { fprint_type(out, &e->cast.type); fprintf(out, ")"); break; + case EXPR_NEW: + fprintf(out, "new "); + fprint_type(out, &e->new.type); + break; case EXPR_IF: if (e->if_.cond) { fprintf(out, "(else)? if "); @@ -1,8 +1,5 @@ main @= fn() { - foo := 'a'; - bar := foo as u8 as f32; - x := "hello"; - x[4] = 's'; - x[3] = foo; + asdf := new &[3]&char; + del new int; + del asdf; }; - diff --git a/tokenizer.c b/tokenizer.c index 2e8127e..7adb7d5 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -45,6 +45,8 @@ typedef enum { KW_RETURN, KW_FN, KW_AS, + KW_NEW, + KW_DEL, KW_INT, KW_I8, KW_I16, @@ -69,6 +71,7 @@ static const char *keywords[KW_COUNT] = "+", "-", "*", "!", "&", "/", "=", "if", "elif", "else", "while", "return", "fn", "as", + "new", "del", "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "float", "f32", "f64", "char", "bool", "true", "false"}; @@ -279,7 +279,14 @@ static bool type_resolve(Typer *tr, Type *t) { return false; } break; - default: break; + case TYPE_PTR: + if (!type_resolve(tr, t->ptr.of)) + return false; + break; + case TYPE_UNKNOWN: + case TYPE_VOID: + case TYPE_BUILTIN: + break; } t->flags |= TYPE_FLAG_RESOLVED; return true; @@ -396,7 +403,7 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_LITERAL_STR: t->kind = TYPE_ARR; t->arr.n = e->strl.len; - t->arr.of = malloc(sizeof *t->arr.of); + t->arr.of = err_malloc(sizeof *t->arr.of); t->arr.of->flags = TYPE_FLAG_RESOLVED; t->arr.of->kind = TYPE_BUILTIN; t->arr.of->builtin = BUILTIN_CHAR; @@ -419,12 +426,19 @@ static bool types_expr(Typer *tr, Expression *e) { if (!type_of_ident(tr, e->where, e->ident, t)) return false; } break; case EXPR_CAST: { - /* TODO: forbid certain casts */ + /* TODO: forbid/warn certain casts */ CastExpr *c = &e->cast; if (!types_expr(tr, c->expr)) return false; *t = c->type; } break; + case EXPR_NEW: + t->kind = TYPE_PTR; + t->ptr.of = err_malloc(sizeof *t->ptr.of); + t->ptr.of = &e->new.type; + if (!type_resolve(tr, t)) + return false; + break; case EXPR_IF: { IfExpr *i = &e->if_; IfExpr *curr = i; @@ -667,6 +681,15 @@ static bool types_expr(Typer *tr, Expression *e) { } *t = *of_type->ptr.of; break; + case UNARY_DEL: + if (of_type->kind != TYPE_PTR) { + char *s = type_to_str(of_type); + err_print(e->where, "Cannot delete non-pointer type %s.", s); + free(s); + return false; + } + t->kind = TYPE_VOID; + break; case UNARY_NOT: if (!type_can_be_truthy(of_type)) { char *s = type_to_str(of_type); |