diff options
author | Nicolas Williams <nico@cryptonector.com> | 2013-06-17 20:21:37 -0500 |
---|---|---|
committer | Nicolas Williams <nico@cryptonector.com> | 2013-06-21 15:27:34 -0500 |
commit | 3403d07912ceb49aff1402ba5b23ecc5f893d608 (patch) | |
tree | f9ebc57dc0b903f8742b2f2b559fa08e1c4b8d80 | |
parent | dc2fe63e42341d1d34cc8e36694b98b9dda16c52 (diff) |
Add mod (and setmod) operators
-rw-r--r-- | builtin.c | 10 | ||||
-rw-r--r-- | lexer.l | 3 | ||||
-rw-r--r-- | parser.y | 14 | ||||
-rw-r--r-- | tests/all.test | 15 |
4 files changed, 38 insertions, 4 deletions
@@ -119,6 +119,15 @@ static jv f_divide(jv input, jv a, jv b) { } } +static jv f_mod(jv input, jv a, jv b) { + jv_free(input); + if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { + return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b)); + } else { + return type_error2(a, b, "cannot be divided"); + } +} + static jv f_equal(jv input, jv a, jv b) { jv_free(input); return jv_bool(jv_equal(a, b)); @@ -476,6 +485,7 @@ static const struct cfunction function_list[] = { {(cfunction_ptr)f_minus, "_minus", 3}, {(cfunction_ptr)f_multiply, "_multiply", 3}, {(cfunction_ptr)f_divide, "_divide", 3}, + {(cfunction_ptr)f_mod, "_mod", 3}, {(cfunction_ptr)f_tonumber, "tonumber", 1}, {(cfunction_ptr)f_tostring, "tostring", 1}, {(cfunction_ptr)f_keys, "keys", 1}, @@ -56,10 +56,11 @@ struct lexer_param; "-=" { return SETMINUS; } "*=" { return SETMULT; } "/=" { return SETDIV; } +"%=" { return SETMOD; } "//=" { return SETDEFINEDOR; } "<=" { return LESSEQ; } ">=" { return GREATEREQ; } -"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"\$"|"<"|">" { return yytext[0];} +"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"%"|"\$"|"<"|">" { return yytext[0];} "["|"{"|"(" { return enter(yytext[0], YY_START, yyscanner); @@ -49,6 +49,7 @@ struct lexer_param; %token <literal> FIELD %token <literal> LITERAL %token <literal> FORMAT +%token SETMOD "%=" %token EQ "==" %token NEQ "!=" %token DEFINEDOR "//" @@ -82,12 +83,12 @@ struct lexer_param; %right '|' %left ',' %right "//" -%nonassoc '=' SETPIPE SETPLUS SETMINUS SETMULT SETDIV SETDEFINEDOR +%nonassoc '=' SETPIPE SETPLUS SETMINUS SETMULT SETDIV SETMOD SETDEFINEDOR %left OR %left AND %nonassoc NEQ EQ '<' '>' LESSEQ GREATEREQ %left '+' '-' -%left '*' '/' +%left '*' '/' '%' %type <blk> Exp Term MkDict MkDictPair ExpD ElseBody QQString FuncDef FuncDefs String @@ -153,6 +154,7 @@ static block gen_binop(block a, block b, int op) { case '-': funcname = "_minus"; break; case '*': funcname = "_multiply"; break; case '/': funcname = "_divide"; break; + case '%': funcname = "_mod"; break; case EQ: funcname = "_equal"; break; case NEQ: funcname = "_notequal"; break; case '<': funcname = "_less"; break; @@ -295,10 +297,18 @@ Exp '/' Exp { $$ = gen_binop($1, $3, '/'); } | +Exp '%' Exp { + $$ = gen_binop($1, $3, '%'); +} | + Exp "/=" Exp { $$ = gen_update($1, $3, '/'); } | +Exp SETMOD Exp { + $$ = gen_update($1, $3, '%'); +} | + Exp "==" Exp { $$ = gen_binop($1, $3, EQ); } | diff --git a/tests/all.test b/tests/all.test index 122b9a61..a9efff0b 100644 --- a/tests/all.test +++ b/tests/all.test @@ -289,6 +289,14 @@ null null [2, 8, 10, 14] +25 % 7 +null +4 + +49732 % 472 +null +172 + 1 + tonumber + ("10" | tonumber) 4 15 @@ -452,12 +460,17 @@ null {"foo": 42} {"foo": 43} -.[] += 2, .[] *= 2, .[] -= 2, .[] /= 2 +.[] += 2, .[] *= 2, .[] -= 2, .[] /= 2, .[] %=2 [1,3,5] [3,5,7] [2,6,10] [-1,1,3] [0.5, 1.5, 2.5] +[1,1,1] + +[.[] % 7] +[-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7] +[0,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,0] .foo += .foo {"foo":2} |