commit 397d47a11a34b9e1dd15971985186591c63e6bbd
parent e59d4e78bf59675ec4697a065b4453088e01d8ad
Author: Demonstrandum <moi@knutsen.co>
Date: Thu, 25 Jun 2020 13:38:16 +0100
Use floats to compute large factorials, add floor and ceil.
Diffstat:
5 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/src/builtin.c b/src/builtin.c
@@ -117,31 +117,60 @@ MATH_WRAPPER(atanh, atanhl)
MATH_WRAPPER(ceil, ceil)
MATH_WRAPPER(floor, floor)
+DataValue *builtin_neg(DataValue input)
+{
+ NumberNode *num = type_check("-", RHS, T_NUMBER, &input);
+ if (num == NULL)
+ return NULL;
+ NumberNode *new_num = malloc(sizeof(NumberNode));
+ memcpy(new_num, num, sizeof(NumberNode));
+ switch (new_num->type) {
+ case INT: {
+ new_num->value.i *= -1;
+ break;
+ }
+ case FLOAT: {
+ new_num->value.f *= -1.0f;
+ break;
+ }
+ default: {
+ ERROR_TYPE = TYPE_ERROR;
+ strcpy(ERROR_MSG, "Unsupported number type.");
+ return NULL;
+ }
+ }
+ DataValue *result = wrap_data(T_NUMBER, new_num);
+ return result;
+}
+
DataValue *builtin_factorial(DataValue input)
{
NumberNode *num = type_check("!", LHS, T_NUMBER, &input);
if (num == NULL)
return NULL;
- if (num->type != INT || num->value.i < 0) {
+ f32 integral = 0;
+ f32 fractional = modff(num->value.f, &integral);
+ if ((num->type == FLOAT && (fractional != 0 || num->value.f < 0))
+ || (num->type == INT && num->value.i < 0)) {
ERROR_TYPE = EXECUTION_ERROR;
strcpy(ERROR_MSG,
"factorial (`!') is only defined for positve integers.");
}
- NumberNode tmp = num_to_int(*num);
+ NumberNode tmp = num_to_float(*num);
NumberNode *new_num = malloc(sizeof(NumberNode));
memcpy(new_num, &tmp, sizeof(NumberNode));
DataValue *result = wrap_data(T_NUMBER, new_num);
- if (new_num->value.i == 0) {
- new_num->value.i = 1;
+ if (new_num->value.f == 0) {
+ new_num->value.f = 1;
result->value = new_num;
return result;
}
- ssize i = new_num->value.i - 1;
+ ssize i = new_num->value.f - 1;
while (i > 1) {
- new_num->value.i *= i;
+ new_num->value.f *= i;
--i;
}
result->value = new_num;
diff --git a/src/builtin.h b/src/builtin.h
@@ -30,7 +30,10 @@ DataValue *builtin_asin(DataValue);
DataValue *builtin_asinh(DataValue);
DataValue *builtin_atan(DataValue);
DataValue *builtin_atanh(DataValue);
+DataValue *builtin_ceil(DataValue);
+DataValue *builtin_floor(DataValue);
DataValue *builtin_factorial(DataValue);
+DataValue *builtin_neg(DataValue);
NumberNode *num_add(NumberNode, NumberNode);
NumberNode *num_sub(NumberNode, NumberNode);
@@ -72,7 +75,11 @@ static const struct _func_name_pair builtin_fns[] = {
{ "arctan", { builtin_atan } },
FUNC_PAIR(atanh),
{ "arctanh", { builtin_atanh } },
+ FUNC_PAIR(ceil),
+ FUNC_PAIR(floor),
FUNC_PAIR(factorial),
{ "!", { builtin_factorial } },
+ FUNC_PAIR(neg),
+ { "-", { builtin_neg } },
};
diff --git a/src/error.c b/src/error.c
@@ -31,7 +31,7 @@ void handle_error()
if (ERROR_TYPE == NO_ERROR)
return;
// Display error.
- printf("\033[31;1m%s\033[0m: %s\n",
+ fprintf(stderr, "\033[31;1m%s\033[0m: %s\n",
error_name(ERROR_TYPE),
ERROR_MSG);
// Reset error values.
diff --git a/src/main.c b/src/main.c
@@ -88,7 +88,7 @@ int main(int argc, char **argv)
printf("\033[%luC\033[1A",
strlen(PROMPT)
+ strlen(response));
- printf("\033[2m ≡ %s\n\033[0m", display_parsetree(tree));
+ printf("\033[2m ≡ %s\033[0m\n", display_parsetree(tree));
DataValue *result = execute(ctx, tree);
diff --git a/src/parse.c b/src/parse.c
@@ -312,8 +312,6 @@ ParseNode *parse_prefix(const Token *token, char **rest)
node->type = UNARY_NODE;
node->node.unary = *unary;
- printf("Parsed prefix as: %s\n\n", display_parsetree(node));
-
break;
}
case TT_LPAREN: {