summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Roantree <stroantree@gmail.com>2012-10-07 22:34:12 +0100
committerStephen Roantree <stroantree@gmail.com>2012-10-07 22:34:12 +0100
commit0618e61e0bd0a58cd222bb4905c51178fe332525 (patch)
tree523b2bdf785927f6f431b341662453231e5c5c02
parenta2643cc0d564033c49bffbd0de9a8e797281e73f (diff)
Add <,>,<=,>= binops
-rw-r--r--builtin.c46
-rw-r--r--lexer.l4
-rw-r--r--parser.y23
-rw-r--r--testdata9
4 files changed, 81 insertions, 1 deletions
diff --git a/builtin.c b/builtin.c
index 1eee5bb5..c6ff785d 100644
--- a/builtin.c
+++ b/builtin.c
@@ -4,6 +4,12 @@
#include "parser.h"
#include "locfile.h"
+enum {
+ CMP_OP_LESS,
+ CMP_OP_GREATER,
+ CMP_OP_LESSEQ,
+ CMP_OP_GREATEREQ
+} _cmp_op;
static void f_plus(jv input[], jv output[]) {
jv_free(input[0]);
@@ -114,6 +120,42 @@ static void f_equal(jv input[], jv output[]) {
output[0] = jv_bool(jv_equal(input[2], input[1]));
}
+static void order_cmp(jv input[], jv output[], int op) {
+ jv_free(input[0]);
+ jv a = input[2];
+ jv b = input[1];
+ if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
+ double da = jv_number_value(a);
+ double db = jv_number_value(b);
+ output[0] = jv_bool((op == CMP_OP_LESS && da < db) ||
+ (op == CMP_OP_LESSEQ && da <= db) ||
+ (op == CMP_OP_GREATEREQ && da >= db) ||
+ (op == CMP_OP_GREATER && da > db));
+ } else {
+ output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to compare order of %s wrt %s",
+ jv_kind_name(jv_get_kind(a)),
+ jv_kind_name(jv_get_kind(b))));
+ jv_free(a);
+ jv_free(b);
+ }
+}
+
+static void f_less(jv input[], jv output[]) {
+ order_cmp(input, output, CMP_OP_LESS);
+}
+
+static void f_greater(jv input[], jv output[]) {
+ order_cmp(input, output, CMP_OP_GREATER);
+}
+
+static void f_lesseq(jv input[], jv output[]) {
+ order_cmp(input, output, CMP_OP_LESSEQ);
+}
+
+static void f_greatereq(jv input[], jv output[]) {
+ order_cmp(input, output, CMP_OP_GREATEREQ);
+}
+
static void f_tonumber(jv input[], jv output[]) {
if (jv_get_kind(input[0]) == JV_KIND_NUMBER) {
output[0] = input[0];
@@ -202,6 +244,10 @@ static struct cfunction function_list[] = {
{f_tonumber, "tonumber", CALL_BUILTIN_1_1},
{f_tostring, "tostring", CALL_BUILTIN_1_1},
{f_equal, "_equal", CALL_BUILTIN_3_1},
+ {f_less, "_less", CALL_BUILTIN_3_1},
+ {f_greater, "_greater", CALL_BUILTIN_3_1},
+ {f_lesseq, "_lesseq", CALL_BUILTIN_3_1},
+ {f_greatereq, "_greatereq", CALL_BUILTIN_3_1},
{f_length, "length", CALL_BUILTIN_1_1},
{f_type, "type", CALL_BUILTIN_1_1},
{f_add, "add", CALL_BUILTIN_1_1},
diff --git a/lexer.l b/lexer.l
index fe0049a9..a353d89b 100644
--- a/lexer.l
+++ b/lexer.l
@@ -48,7 +48,9 @@
"*=" { return SETMULT; }
"/=" { return SETDIV; }
"//=" { return SETDEFINEDOR; }
-"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"\$" { return yytext[0];}
+"<=" { return LESSEQ; }
+">=" { return GREATEREQ; }
+"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"\$"|"<"|">" { return yytext[0];}
"["|"{"|"(" {
return enter(yytext[0], YY_START, yyscanner);
diff --git a/parser.y b/parser.y
index 0fda65bd..94700aee 100644
--- a/parser.y
+++ b/parser.y
@@ -59,6 +59,8 @@
%token SETMULT "*="
%token SETDIV "/="
%token SETDEFINEDOR "//="
+%token LESSEQ "<="
+%token GREATEREQ ">="
%token QQSTRING_START
%token <literal> QQSTRING_TEXT
@@ -77,6 +79,7 @@
%nonassoc EQ
%left '+' '-'
%left '*' '/'
+%right '<' '>' LESSEQ GREATEREQ
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody QQString FuncDef FuncDefs
@@ -137,6 +140,10 @@ static block gen_binop(block a, block b, int op) {
case '*': funcname = "_multiply"; break;
case '/': funcname = "_divide"; break;
case EQ: funcname = "_equal"; break;
+ case '<': funcname = "_less"; break;
+ case '>': funcname = "_greater"; break;
+ case LESSEQ: funcname = "_lesseq"; break;
+ case GREATEREQ: funcname = "_greatereq"; break;
}
assert(funcname);
@@ -273,6 +280,22 @@ Exp "==" Exp {
$$ = gen_binop($1, $3, EQ);
} |
+Exp '<' Exp {
+ $$ = gen_binop($1, $3, '<');
+} |
+
+Exp '>' Exp {
+ $$ = gen_binop($1, $3, '>');
+} |
+
+Exp "<=" Exp {
+ $$ = gen_binop($1, $3, LESSEQ);
+} |
+
+Exp ">=" Exp {
+ $$ = gen_binop($1, $3, GREATEREQ);
+} |
+
QQSTRING_START QQString QQSTRING_END {
$$ = $2;
} |
diff --git a/testdata b/testdata
index 307eaa62..c37dee93 100644
--- a/testdata
+++ b/testdata
@@ -348,3 +348,12 @@ def inc(x): x |= .+1; inc(.[].a)
[.[] | not]
[1,0,false,null,true,"hello"]
[false,false,true,true,false,false]
+
+# Check numeric comparison binops
+[10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20]
+{}
+[true,false,false,false,false,true]
+
+[10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20]
+{}
+[true,true,false,false,true,true] \ No newline at end of file