diff --git a/c/builtin.c b/c/builtin.c index b65bb09b..7943675d 100644 --- a/c/builtin.c +++ b/c/builtin.c @@ -100,6 +100,30 @@ static void f_divide(jv input[], jv output[]) { } } +static void f_tonumber(jv input[], jv output[]) { + if (jv_get_kind(input[0]) == JV_KIND_NUMBER) { + output[0] = input[0]; + } else if (jv_get_kind(input[0]) == JV_KIND_STRING) { + jv parsed = jv_parse(jv_string_value(input[0])); + if (!jv_is_valid(parsed)) { + jv_free(input[0]); + output[0] = parsed; + } else if (jv_get_kind(parsed) != JV_KIND_NUMBER) { + output[0] = jv_invalid_with_msg(jv_string_fmt("'%s' is not a number", + jv_string_value(input[0]))); + jv_free(input[0]); + } else { + jv_free(input[0]); + output[0] = parsed; + } + } else { + output[0] = jv_invalid_with_msg(jv_string_fmt("Cannot parse %s as a number", + jv_kind_name(jv_get_kind(input[0])))); + jv_free(input[0]); + return; + } +} + struct cfunction function_list[] = { {f_true, "true", CALL_BUILTIN_1_1}, {f_false, "false", CALL_BUILTIN_1_1}, @@ -108,5 +132,6 @@ struct cfunction function_list[] = { {f_minus, "_minus", CALL_BUILTIN_3_1}, {f_multiply, "_multiply", CALL_BUILTIN_3_1}, {f_divide, "_divide", CALL_BUILTIN_3_1}, + {f_tonumber, "tonumber", CALL_BUILTIN_1_1}, }; struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])}; diff --git a/c/testdata b/c/testdata index eb9f0c5f..45140242 100644 --- a/c/testdata +++ b/c/testdata @@ -183,6 +183,10 @@ null null 10 +1 + tonumber + ("10" | tonumber) +4 +15 + # # User-defined functions # Oh god.