2026-03-25 11:30:12 -06:00
|
|
|
#include "evaluator.h"
|
2026-04-13 08:44:30 -06:00
|
|
|
#include "arena.h"
|
2026-03-25 11:30:12 -06:00
|
|
|
#include "lexer.h"
|
2026-04-13 08:44:30 -06:00
|
|
|
#include "parser.h"
|
2026-05-13 12:13:07 -06:00
|
|
|
#include <stdbool.h>
|
2026-03-25 11:30:12 -06:00
|
|
|
#include <stdint.h>
|
2026-05-12 18:15:36 -06:00
|
|
|
#include <math.h>
|
2026-04-13 07:57:36 -06:00
|
|
|
|
2026-03-25 11:30:12 -06:00
|
|
|
|
2026-05-13 12:13:07 -06:00
|
|
|
EvaluatorResult evaluate_tree(Node *tree) {
|
2026-03-25 11:30:12 -06:00
|
|
|
if (tree->type == NODE_BINARY_OP) {
|
2026-05-13 12:13:07 -06:00
|
|
|
Operator op = tree->binary.op;
|
|
|
|
|
Node *left = tree->binary.left;
|
|
|
|
|
Node *right = tree->binary.right;
|
2026-03-26 09:25:40 -06:00
|
|
|
|
|
|
|
|
switch (op) {
|
2026-05-13 12:13:07 -06:00
|
|
|
case OP_ADD: {
|
|
|
|
|
EvaluatorResult left_result = evaluate_tree(left);
|
|
|
|
|
EvaluatorResult right_result = evaluate_tree(right);
|
|
|
|
|
if (!left_result.is_valid || !right_result.is_valid) {
|
|
|
|
|
return left_result;
|
|
|
|
|
}
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = true,
|
|
|
|
|
.val = left_result.val + right_result.val,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
case OP_SUB: {
|
|
|
|
|
EvaluatorResult left_result = evaluate_tree(left);
|
|
|
|
|
EvaluatorResult right_result = evaluate_tree(right);
|
|
|
|
|
if (!left_result.is_valid || !right_result.is_valid) {
|
|
|
|
|
return left_result;
|
|
|
|
|
}
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = true,
|
|
|
|
|
.val = left_result.val - right_result.val,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
case OP_MUL: {
|
|
|
|
|
EvaluatorResult left_result = evaluate_tree(left);
|
|
|
|
|
EvaluatorResult right_result = evaluate_tree(right);
|
|
|
|
|
if (!left_result.is_valid || !right_result.is_valid) {
|
|
|
|
|
return left_result;
|
|
|
|
|
}
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = true,
|
|
|
|
|
.val = left_result.val * right_result.val,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
case OP_DIV: {
|
|
|
|
|
EvaluatorResult left_result = evaluate_tree(left);
|
|
|
|
|
EvaluatorResult right_result = evaluate_tree(right);
|
|
|
|
|
if (!left_result.is_valid || !right_result.is_valid) {
|
|
|
|
|
return left_result;
|
|
|
|
|
}
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = true,
|
|
|
|
|
.val = left_result.val / right_result.val,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
case OP_POW: {
|
|
|
|
|
EvaluatorResult left_result = evaluate_tree(left);
|
|
|
|
|
EvaluatorResult right_result = evaluate_tree(right);
|
|
|
|
|
if (!left_result.is_valid || !right_result.is_valid) {
|
|
|
|
|
return left_result;
|
|
|
|
|
}
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = true,
|
|
|
|
|
.val = pow(left_result.val, right_result.val),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = false,
|
|
|
|
|
.err = EVALUATOR_INVALID_TREE,
|
|
|
|
|
};
|
2026-03-25 11:30:12 -06:00
|
|
|
}
|
2026-05-13 12:13:07 -06:00
|
|
|
} else if (tree->type == NODE_UNARY_OP) {
|
|
|
|
|
|
2026-03-25 11:30:12 -06:00
|
|
|
}
|
2026-04-13 08:44:30 -06:00
|
|
|
|
|
|
|
|
int64_t return_val = tree->data.integer;
|
|
|
|
|
return return_val;
|
2026-03-25 11:30:12 -06:00
|
|
|
}
|
|
|
|
|
|
2026-05-13 12:13:07 -06:00
|
|
|
EvaluatorResult evaluate(ParseResult context) {
|
|
|
|
|
if (!context.is_valid) {
|
|
|
|
|
return (EvaluatorResult) {
|
|
|
|
|
.is_valid = false,
|
|
|
|
|
.err = EVALUATOR_INVALID_PARSING,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EvaluatorResult result = evaluate_tree(context.tree);
|
|
|
|
|
|
2026-04-13 08:44:30 -06:00
|
|
|
arena_destroy(&context.arena);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|