diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-09-26 13:34:08 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-09-26 13:34:08 -0400 |
commit | 5a8eb5fee273ce3eceeec45a1ac876a37faf981f (patch) | |
tree | 748c72131c621a633150e6f74f0faed541c0cbca | |
parent | b7fe781138c1a775cc44ec1448e94305b3b8a0dd (diff) |
added comparison operators
-rw-r--r-- | eval.c | 51 | ||||
-rw-r--r-- | identifiers.c | 8 | ||||
-rw-r--r-- | parse.c | 36 | ||||
-rw-r--r-- | test.toc | 14 | ||||
-rw-r--r-- | tokenizer.c | 11 | ||||
-rw-r--r-- | types.c | 52 |
6 files changed, 139 insertions, 33 deletions
@@ -70,8 +70,13 @@ static bool eval_expr(Expression *e, Value *v) { /* NOTE: this will need to change for short-circuiting */ if (!eval_expr(e->binary.lhs, &lhs)) return false; if (!eval_expr(e->binary.rhs, &rhs)) return false; + if (e->type.kind != TYPE_BUILTIN) { + err_print(e->where, "Operators can only be applied to builtin types."); + return false; + } bool is_int = type_builtin_is_integer(e->type.builtin); bool is_float = type_builtin_is_floating(e->type.builtin); + bool is_bool = e->type.builtin == BUILTIN_BOOL; switch (e->binary.op) { case BINARY_PLUS: if (is_int) { @@ -102,6 +107,52 @@ static bool eval_expr(Expression *e, Value *v) { v->floatv = lhs.floatv / rhs.floatv; } else assert(0); return true; + case BINARY_EQ: + if (is_int) { + v->boolv = lhs.intv == rhs.intv; + } else if (is_float) { + v->boolv = lhs.floatv == rhs.floatv; + } else if (is_bool) { + v->boolv = lhs.boolv == rhs.boolv; + } else assert(0); + return true; + case BINARY_NE: + if (is_int) { + v->boolv = lhs.intv != rhs.intv; + } else if (is_float) { + v->boolv = lhs.floatv != rhs.floatv; + } else if (is_bool) { + v->boolv = lhs.boolv != rhs.boolv; + } else assert(0); + return true; + case BINARY_GT: + if (is_int) { + v->boolv = lhs.intv > rhs.intv; + } else if (is_float) { + v->boolv = lhs.floatv > rhs.floatv; + } else assert(0); + return true; + case BINARY_GE: + if (is_int) { + v->boolv = lhs.intv >= rhs.intv; + } else if (is_float) { + v->boolv = lhs.floatv >= rhs.floatv; + } else assert(0); + return true; + case BINARY_LT: + if (is_int) { + v->boolv = lhs.intv < rhs.intv; + } else if (is_float) { + v->boolv = lhs.floatv < rhs.floatv; + } else assert(0); + return true; + case BINARY_LE: + if (is_int) { + v->boolv = lhs.intv <= rhs.intv; + } else if (is_float) { + v->boolv = lhs.floatv <= rhs.floatv; + } else assert(0); + return true; case BINARY_SET: return true; case BINARY_COMMA: diff --git a/identifiers.c b/identifiers.c index 168bf7b..6b19d18 100644 --- a/identifiers.c +++ b/identifiers.c @@ -41,7 +41,7 @@ static int isident(int c) { return 1; if (c >= '0' && c <= '9') return 1; - if (c == '_' || c == '.') return 1; + if (c == '_') return 1; #if CHAR_MIN < 0 if (c < 0) /* on systems where char = signed char, UTF-8 characters are probably < 0? */ return 1; @@ -135,11 +135,7 @@ static void fprint_ident_reduced_charset(FILE *out, Identifier id) { fprintf(out, "x__%x",c); } else { char chr = (char)ident_uchar_to_char(c); - if (chr == '.') { - fprintf(out, "__"); /* replace . with __ */ - } else { - fputc(chr, out); - } + fputc(chr, out); } } @@ -91,6 +91,12 @@ typedef enum { BINARY_MUL, BINARY_DIV, BINARY_COMMA, + BINARY_GT, + BINARY_LT, + BINARY_GE, + BINARY_LE, + BINARY_EQ, + BINARY_NE, BINARY_AT_INDEX /* e.g. x[i] */ } BinaryOp; @@ -232,6 +238,12 @@ static const char *binary_op_to_str(BinaryOp b) { case BINARY_SET: return "="; case BINARY_COMMA: return ","; case BINARY_AT_INDEX: return "[]"; + case BINARY_LT: return "<"; + case BINARY_LE: return "<="; + case BINARY_GT: return ">"; + case BINARY_GE: return ">="; + case BINARY_EQ: return "=="; + case BINARY_NE: return "!="; } assert(0); return ""; @@ -386,6 +398,12 @@ static Expression *parser_new_expr(Parser *p) { static int op_precedence(Keyword op) { switch (op) { case KW_EQ: return 0; + case KW_LT: return 3; + case KW_GT: return 3; + case KW_LE: return 3; + case KW_GE: return 3; + case KW_EQEQ: return 3; + case KW_NE: return 3; case KW_COMMA: return 5; case KW_PLUS: return 10; case KW_MINUS: return 20; @@ -1125,6 +1143,24 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_MINUS: op = BINARY_MINUS; break; + case KW_EQEQ: + op = BINARY_EQ; + break; + case KW_NE: + op = BINARY_NE; + break; + case KW_LT: + op = BINARY_LT; + break; + case KW_LE: + op = BINARY_LE; + break; + case KW_GT: + op = BINARY_GT; + break; + case KW_GE: + op = BINARY_GE; + break; case KW_EQ: op = BINARY_SET; break; @@ -1,9 +1,11 @@ main @= fn() { - foo @= fn(x: int) { return; }; - // b := !(5 > 3 && 4 <= 3 && 3 >= 2 || 0); - // b := !(5 < 3); - x @= !!!!!!!false; - - // foo := 5 < 3; + //foo @= fn(x: int) { return; }; + // b := !(5 > 3 && 4 <= 3 && 3 >= 2 || 0 == 1 || 5 != 3); + b := !(5 < 3); + a := (5 == 3); + C @= 3 != 4; + //x @= !!!!!!!false; + +// foo := 5 < 3; }; diff --git a/tokenizer.c b/tokenizer.c index 5af4297..dc46cd5 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -15,7 +15,6 @@ typedef enum { typedef enum { KW_SEMICOLON, - KW_EQ, KW_COLON, KW_AT, KW_COMMA, @@ -26,6 +25,7 @@ typedef enum { KW_LSQUARE, KW_RSQUARE, KW_EQEQ, + KW_NE, KW_LT, KW_LE, KW_GT, @@ -36,7 +36,8 @@ typedef enum { KW_EXCLAMATION, KW_AMPERSAND, KW_SLASH, - KW_LAST_SYMBOL = KW_SLASH, /* last one entirely consisting of symbols */ + KW_EQ, + KW_LAST_SYMBOL = KW_EQ, /* last one entirely consisting of symbols */ KW_IF, KW_ELIF, KW_ELSE, @@ -62,8 +63,10 @@ typedef enum { } Keyword; static const char *keywords[KW_COUNT] = - {";", "=", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", "<", "<=", ">", ">=", - "+", "-", "*", "!", "&", "/", "if", "elif", "else", "while", "return", "fn", + {";", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", "!=", "<", "<=", ">", ">=", + "+", "-", "*", "!", "&", "/", + "=", + "if", "elif", "else", "while", "return", "fn", "bool", "true", "false", "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "float", "f32", "f64"}; @@ -581,7 +581,13 @@ static bool types_expr(Typer *tr, Expression *e) { case BINARY_PLUS: case BINARY_MINUS: case BINARY_MUL: - case BINARY_DIV: { + case BINARY_DIV: + case BINARY_LT: + case BINARY_GT: + case BINARY_LE: + case BINARY_GE: + case BINARY_EQ: + case BINARY_NE: { bool match = true; if (e->binary.op != BINARY_SET) { /* numerical binary ops */ @@ -594,26 +600,38 @@ static bool types_expr(Typer *tr, Expression *e) { } } if (match) { - if (e->binary.op == BINARY_SET) { + switch (e->binary.op) { + case BINARY_SET: /* type of x = y is always void */ t->kind = TYPE_VOID; break; - } - int lhs_is_flexible = lhs_type->flags & TYPE_FLAG_FLEXIBLE; - int rhs_is_flexible = rhs_type->flags & TYPE_FLAG_FLEXIBLE; - if (lhs_is_flexible && rhs_is_flexible) { - *t = *lhs_type; - if (rhs_type->builtin == BUILTIN_F32) { - /* promote to float */ - t->builtin = BUILTIN_F32; - } - } else if (type_eq(lhs_type, rhs_type)) { - if (!lhs_is_flexible) + case BINARY_LT: + case BINARY_GT: + case BINARY_LE: + case BINARY_GE: + case BINARY_EQ: + case BINARY_NE: + t->kind = TYPE_BUILTIN; + t->builtin = BUILTIN_BOOL; + break; + default: { + int lhs_is_flexible = lhs_type->flags & TYPE_FLAG_FLEXIBLE; + int rhs_is_flexible = rhs_type->flags & TYPE_FLAG_FLEXIBLE; + if (lhs_is_flexible && rhs_is_flexible) { *t = *lhs_type; - else - *t = *rhs_type; - } else { - match = false; + if (rhs_type->builtin == BUILTIN_F32) { + /* promote to float */ + t->builtin = BUILTIN_F32; + } + } else if (type_eq(lhs_type, rhs_type)) { + if (!lhs_is_flexible) + *t = *lhs_type; + else + *t = *rhs_type; + } else { + match = false; + } + } break; } } if (!match) { |