diff options
-rw-r--r-- | eval.c | 12 | ||||
-rw-r--r-- | parse.c | 13 | ||||
-rw-r--r-- | test.toc | 7 | ||||
-rw-r--r-- | types.c | 16 |
4 files changed, 34 insertions, 14 deletions
@@ -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); @@ -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; @@ -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; }; @@ -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: { |