From aa3ebdfe9b714548fb0d5cfe0265950b1392fb1e Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Mon, 10 Sep 2012 16:57:17 +0100 Subject: [PATCH] Multiplication and division operators. It is an error to use these on anything but numbers. Maybe later implementing python/ruby-style ("a" * 100) might be handy. --- c/builtin.c | 32 ++++++++++++++++++++++++++++++++ c/lexer.l | 2 +- c/parser.y | 11 +++++++++++ c/testdata | 8 ++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/c/builtin.c b/c/builtin.c index 65ecb52..b65bb09 100644 --- a/c/builtin.c +++ b/c/builtin.c @@ -70,11 +70,43 @@ static void f_minus(jv input[], jv output[]) { } } +static void f_multiply(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 { + output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to multiply %s and %s", + jv_kind_name(jv_get_kind(a)), + jv_kind_name(jv_get_kind(b)))); + jv_free(a); + jv_free(b); + } +} + +static void f_divide(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 { + output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to divide %s by %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}, + {f_multiply, "_multiply", CALL_BUILTIN_3_1}, + {f_divide, "_divide", CALL_BUILTIN_3_1}, }; struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])}; diff --git a/c/lexer.l b/c/lexer.l index 1b74d43..1794b9f 100644 --- a/c/lexer.l +++ b/c/lexer.l @@ -22,7 +22,7 @@ "not" { return NOT; } "end" { return END; } "//" { return DEFINEDOR; } -"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"\$" { return yytext[0];} +"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"*"|"/"|"\$" { return yytext[0];} \"(\\.|[^\\"])*\" | -?[0-9.]+([eE][+-]?[0-9]+)? { diff --git a/c/parser.y b/c/parser.y index 72b91a1..225a324 100644 --- a/c/parser.y +++ b/c/parser.y @@ -43,6 +43,7 @@ %left OR %left AND %left '+' '-' +%left '*' '/' %type Exp Term MkDict MkDictPair ExpD ElseBody @@ -68,6 +69,8 @@ static block gen_binop(block a, block b, char op) { switch (op) { case '+': funcname = "_plus"; break; case '-': funcname = "_minus"; break; + case '*': funcname = "_multiply"; break; + case '/': funcname = "_divide"; break; } assert(funcname); @@ -157,6 +160,14 @@ Exp '-' Exp { $$ = gen_binop($1, $3, '-'); } | +Exp '*' Exp { + $$ = gen_binop($1, $3, '*'); +} | + +Exp '/' Exp { + $$ = gen_binop($1, $3, '/'); +} | + Term { $$ = $1; } diff --git a/c/testdata b/c/testdata index 6386ac0..eb9f0c5 100644 --- a/c/testdata +++ b/c/testdata @@ -175,6 +175,14 @@ null 1 [2,4] +[10 * 20, 20 / .] +4 +[200, 5] + +1 + 2 * 2 + 10 / 2 +null +10 + # # User-defined functions # Oh god. -- 2.40.0