diff options
Diffstat (limited to 'eval.c')
| -rw-r--r-- | eval.c | 46 |
1 files changed, 43 insertions, 3 deletions
@@ -1,14 +1,54 @@ #include <assert.h> +#include <inttypes.h> #include <stdio.h> #include "eval.h" -static int evaluate_value(const struct Node* node, long* out) +static int evaluate_value(const struct Node* node, int64_t* out); + +static int complain(const struct Node* node, const char* message) +{ + (void)fprintf(stderr, "line %d: %s\n", node->line, message); + return 1; +} + +static int evaluate_operands(const struct Node* node, int64_t* left, int64_t* right) { + if (evaluate_value(node->first, left)) + return 1; + + return evaluate_value(node->second, right); +} + +static int evaluate_value(const struct Node* node, int64_t* out) +{ + int64_t left = 0; + int64_t right = 0; switch (node->kind) { case VALUE_DIFFERENCE: - *out = (long)node->first->character - (long)node->second->character; + *out = (int64_t)node->first->character - (int64_t)node->second->character; + return 0; + case VALUE_SUM: + if (evaluate_operands(node, &left, &right)) + return 1; + + *out = left + right; + return 0; + case VALUE_PRODUCT: + if (evaluate_operands(node, &left, &right)) + return 1; + + *out = left * right; + return 0; + case VALUE_QUOTIENT: + if (evaluate_operands(node, &left, &right)) + return 1; + + if (right == 0) + return complain(node, "division by zero"); + + *out = left / right; return 0; default: break; } @@ -42,7 +82,7 @@ static enum RunStatus emit(const struct Node* node) return RUN_FAILED; if (type.kind == KIND_VALUE) - (void)printf("%ld\n", type.number); + (void)printf("%" PRId64 "\n", type.number); return RUN_DONE; } |
