}
}
+static void f_minus(jv input[], jv output[]) {
+ 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) {
+ output[0] = jv_number(jv_number_value(a) - jv_number_value(b));
+ } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
+ jv out = jv_array();
+ for (int i=0; i<jv_array_length(jv_copy(a)); i++) {
+ jv x = jv_array_get(jv_copy(a), i);
+ int include = 1;
+ for (int j=0; j<jv_array_length(jv_copy(b)); j++) {
+ if (jv_equal(jv_copy(x), jv_array_get(jv_copy(b), j))) {
+ include = 0;
+ break;
+ }
+ }
+ if (include)
+ out = jv_array_append(out, jv_copy(x));
+ jv_free(x);
+ }
+ jv_free(a);
+ jv_free(b);
+ output[0] = out;
+ } else {
+ output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to subtract %s and %s",
+ jv_kind_name(jv_get_kind(a)),
+ jv_kind_name(jv_get_kind(b))));
+ jv_free(a);
+ jv_free(b);
+ }
+}
+
struct cfunction function_list[] = {
{f_true, "true", CALL_BUILTIN_1_1},
{f_false, "false", CALL_BUILTIN_1_1},
{f_null, "null", CALL_BUILTIN_1_1},
{f_plus, "_plus", CALL_BUILTIN_3_1},
+ {f_minus, "_minus", CALL_BUILTIN_3_1},
};
struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])};
"not" { return NOT; }
"end" { return END; }
"//" { return DEFINEDOR; }
-"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
+"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"\$" { return yytext[0];}
\"(\\.|[^\\"])*\" |
-?[0-9.]+([eE][+-]?[0-9]+)? {
%nonassoc EQ
%left OR
%left AND
-%left '+'
+%left '+' '-'
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody
-
%{
#include "lexer.yy.h"
void yyerror(YYLTYPE* loc, block* answer, yyscan_t lexer, const char *s){
return block_join(obj, block_join(gen_subexp(key), gen_op_simple(INDEX)));
}
+static block gen_binop(block a, block b, char op) {
+ const char* funcname = 0;
+ switch (op) {
+ case '+': funcname = "_plus"; break;
+ case '-': funcname = "_minus"; break;
+ }
+ assert(funcname);
+
+ block c = gen_noop();
+ block_append(&c, gen_subexp(a));
+ block_append(&c, gen_subexp(b));
+ block_append(&c, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, funcname)));
+ return c;
+}
+
%}
%%
} |
Exp '+' Exp {
- $$ = gen_noop();
- block_append(&$$, gen_subexp($1));
- block_append(&$$, gen_subexp($3));
- block_append(&$$, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, "_plus")));
+ $$ = gen_binop($1, $3, '+');
+} |
+
+Exp '-' Exp {
+ $$ = gen_binop($1, $3, '-');
} |
Term {
$$ = $2;
}
-
ExpD:
ExpD '|' ExpD {
$$ = block_join($1, $3);
"\u0000\u0020\u0000"
"\u0000 \u0000\u0000 \u0000"
+42 - .
+11
+31
+
+[1,2,3,4,1] - [.,3]
+1
+[2,4]
+
#
# User-defined functions
# Oh god.