summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--abbrevs.txt1
-rw-r--r--eval.c6
-rw-r--r--main.c3
-rw-r--r--parse.c45
-rw-r--r--test.toc9
-rw-r--r--tokenizer.c3
-rw-r--r--types.c29
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
diff --git a/eval.c b/eval.c
index d0b5fa6..68b0d02 100644
--- a/eval.c
+++ b/eval.c
@@ -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:
diff --git a/main.c b/main.c
index f0df649..aada098 100644
--- a/main.c
+++ b/main.c
@@ -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
*/
diff --git a/parse.c b/parse.c
index 6e91f11..2d5e3d9 100644
--- a/parse.c
+++ b/parse.c
@@ -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 ");
diff --git a/test.toc b/test.toc
index 4d9ab40..d3d1891 100644
--- a/test.toc
+++ b/test.toc
@@ -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"};
diff --git a/types.c b/types.c
index 2596596..dd724c3 100644
--- a/types.c
+++ b/types.c
@@ -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);