summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-09-26 13:34:08 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-09-26 13:34:08 -0400
commit5a8eb5fee273ce3eceeec45a1ac876a37faf981f (patch)
tree748c72131c621a633150e6f74f0faed541c0cbca
parentb7fe781138c1a775cc44ec1448e94305b3b8a0dd (diff)
added comparison operators
-rw-r--r--eval.c51
-rw-r--r--identifiers.c8
-rw-r--r--parse.c36
-rw-r--r--test.toc14
-rw-r--r--tokenizer.c11
-rw-r--r--types.c52
6 files changed, 139 insertions, 33 deletions
diff --git a/eval.c b/eval.c
index 4d719a4..01a3fbe 100644
--- a/eval.c
+++ b/eval.c
@@ -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);
}
}
diff --git a/parse.c b/parse.c
index 2d464dc..f38c8bf 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/test.toc b/test.toc
index 1f68afa..2bdce87 100644
--- a/test.toc
+++ b/test.toc
@@ -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"};
diff --git a/types.c b/types.c
index 1777f9b..6acb752 100644
--- a/types.c
+++ b/types.c
@@ -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) {