summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c12
-rw-r--r--parse.c13
-rw-r--r--test.toc7
-rw-r--r--types.c16
4 files changed, 34 insertions, 14 deletions
diff --git a/eval.c b/eval.c
index 9a4dcba..4d719a4 100644
--- a/eval.c
+++ b/eval.c
@@ -8,10 +8,11 @@ typedef struct Value {
};
} Value;
-/* static bool eval_truthiness(Expression *e, Value *v) { */
-/* /\* TODO *\/ */
-/* return true; */
-/* } */
+static bool eval_truthiness(Expression *e, Value *v) {
+ /* TODO */
+ (void)e,(void)v;
+ return true;
+}
/* NOTE: expr must be typed before it can be evaluated */
static bool eval_expr(Expression *e, Value *v) {
@@ -50,6 +51,9 @@ static bool eval_expr(Expression *e, Value *v) {
}
return true;
}
+ case UNARY_NOT:
+ v->boolv = !eval_truthiness(e, v);
+ return true;
case UNARY_ADDRESS:
v->points_to = err_malloc(sizeof *v->points_to); /* OPTIM */
return eval_expr(e->unary.of, v->points_to);
diff --git a/parse.c b/parse.c
index f9cbed6..2d464dc 100644
--- a/parse.c
+++ b/parse.c
@@ -80,7 +80,8 @@ typedef enum {
typedef enum {
UNARY_MINUS,
UNARY_ADDRESS, /* &x */
- UNARY_DEREF
+ UNARY_DEREF, /* *x */
+ UNARY_NOT /* !x */
} UnaryOp;
typedef enum {
@@ -216,6 +217,7 @@ static const char *unary_op_to_str(UnaryOp u) {
case UNARY_MINUS: return "-";
case UNARY_ADDRESS: return "&";
case UNARY_DEREF: return "*";
+ case UNARY_NOT: return "!";
}
assert(0);
return "";
@@ -390,6 +392,7 @@ static int op_precedence(Keyword op) {
case KW_AMPERSAND: return 25;
case KW_ASTERISK: return 30;
case KW_SLASH: return 40;
+ case KW_EXCLAMATION: return 50;
default: return NOT_AN_OP;
}
}
@@ -1078,7 +1081,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
if (lowest_precedence_op == t->token) {
/* Unary */
UnaryOp op;
- bool is_unary;
+ bool is_unary = true;
switch (lowest_precedence_op->kw) {
case KW_PLUS:
/* unary + is ignored entirely */
@@ -1086,17 +1089,17 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
/* re-parse this expression without + */
return parse_expr(p, e, end);
case KW_MINUS:
- is_unary = true;
op = UNARY_MINUS;
break;
case KW_AMPERSAND:
- is_unary = true;
op = UNARY_ADDRESS;
break;
case KW_ASTERISK:
- is_unary = true;
op = UNARY_DEREF;
break;
+ case KW_EXCLAMATION:
+ op = UNARY_NOT;
+ break;
default:
is_unary = false;
break;
diff --git a/test.toc b/test.toc
index aa89df9..1f68afa 100644
--- a/test.toc
+++ b/test.toc
@@ -1,8 +1,9 @@
main @= fn() {
foo @= fn(x: int) { return; };
- //b := !(5 > 3 && 4 <= 3 && 3 >= 2 || 0);
- //b := !(5 < 3);
- x : bool = true;
+ // b := !(5 > 3 && 4 <= 3 && 3 >= 2 || 0);
+ // b := !(5 < 3);
+ x @= !!!!!!!false;
+ // foo := 5 < 3;
};
diff --git a/types.c b/types.c
index 5d1148b..1777f9b 100644
--- a/types.c
+++ b/types.c
@@ -257,9 +257,12 @@ static bool type_resolve(Typer *tr, Type *t) {
Value val;
Expression *n_expr = t->arr.n_expr;
if (!types_expr(tr, n_expr)) return false;
- if (n_expr->type.kind != TYPE_BUILTIN || !type_builtin_is_integer(n_expr->type.builtin))
+ if (n_expr->type.kind != TYPE_BUILTIN || !type_builtin_is_integer(n_expr->type.builtin)) {
+ char *s = type_to_str(&n_expr->type);
+ err_print(n_expr->where, "Cannot use type %s as the size of an array (it's not an integer type).", s);
+ free(s);
return false;
-
+ }
if (!eval_expr(n_expr, &val)) return false; /* resolve N */
Integer size = val.intv;
if (size < 0)
@@ -551,6 +554,15 @@ static bool types_expr(Typer *tr, Expression *e) {
}
*t = *of_type->ptr.of;
break;
+ case UNARY_NOT:
+ if (!type_can_be_truthy(of_type)) {
+ char *s = type_to_str(of_type);
+ err_print(e->where, "Type '%s' cannot be truthy, so the not operator cannot be applied to it.", s);
+ free(s);
+ return false;
+ }
+ t->kind = TYPE_BUILTIN;
+ t->builtin = BUILTIN_BOOL;
}
} break;
case EXPR_BINARY_OP: {