diff options
| author | hachem <im@hachem.wtf> | 2026-09-19 14:38:55 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-19 14:38:55 +0200 |
| commit | b79902cd36b2c5b54bbf0f07078fc528754977b2 (patch) | |
| tree | 0f3baa55b58831c46c7631619f76eef5cb371f71 /eval.c | |
| parent | 7160bdb390ef1c9bdcfb0c075b33be39d62860f3 (diff) | |
feat: variables and shi
Diffstat (limited to 'eval.c')
| -rw-r--r-- | eval.c | 140 |
1 files changed, 107 insertions, 33 deletions
@@ -2,12 +2,47 @@ #include <inttypes.h> #include <stdbool.h> #include <stdio.h> +#include <string.h> #include "eval.h" -static int evaluate_type(const struct Node* node, struct Type* out); -static int evaluate_value(const struct Node* node, int64_t* out); -static int evaluate_condition(const struct Node* node, bool* out); +static int evaluate_type(struct Machine* machine, const struct Node* node, struct Type* out); +static int evaluate_value(struct Machine* machine, const struct Node* node, int64_t* out); +static int evaluate_condition(struct Machine* machine, const struct Node* node, bool* out); + +void machine_init(struct Machine* machine) +{ + memset(machine, 0, sizeof *machine); +} + +static struct Variable* find_variable(struct Machine* machine, const char* name) +{ + for (size_t index = 0; index < VARIABLES_MAX; index++) + { + struct Variable* variable = &machine->variables[index]; + if (variable->declared && strcmp(variable->name, name) == 0) + return variable; + } + + return NULL; +} + +static bool bind_variable(struct Machine* machine, const char* name, int64_t value) +{ + for (size_t index = 0; index < VARIABLES_MAX; index++) + { + struct Variable* variable = &machine->variables[index]; + if (variable->declared) + continue; + + (void)snprintf(variable->name, sizeof variable->name, "%s", name); + variable->value = value; + variable->declared = true; + return true; + } + + return false; +} static int complain(const struct Node* node, const char* message) { @@ -15,19 +50,21 @@ static int complain(const struct Node* node, const char* message) return 1; } -static int evaluate_operands(const struct Node* node, int64_t* left, int64_t* right) +static int evaluate_operands(struct Machine* machine, const struct Node* node, int64_t* left, + int64_t* right) { - if (evaluate_value(node->first, left)) + if (evaluate_value(machine, node->first, left)) return 1; - return evaluate_value(node->second, right); + return evaluate_value(machine, node->second, right); } -static int evaluate_value(const struct Node* node, int64_t* out) +static int evaluate_value(struct Machine* machine, const struct Node* node, int64_t* out) { int64_t left = 0; int64_t right = 0; struct Type type; + struct Variable* variable = NULL; bool truth = false; switch (node->kind) { @@ -35,19 +72,19 @@ static int evaluate_value(const struct Node* node, int64_t* out) *out = (int64_t)node->first->character - (int64_t)node->second->character; return 0; case VALUE_SUM: - if (evaluate_operands(node, &left, &right)) + if (evaluate_operands(machine, node, &left, &right)) return 1; *out = left + right; return 0; case VALUE_PRODUCT: - if (evaluate_operands(node, &left, &right)) + if (evaluate_operands(machine, node, &left, &right)) return 1; *out = left * right; return 0; case VALUE_QUOTIENT: - if (evaluate_operands(node, &left, &right)) + if (evaluate_operands(machine, node, &left, &right)) return 1; if (right == 0) @@ -57,16 +94,23 @@ static int evaluate_value(const struct Node* node, int64_t* out) return 0; case VALUE_EXTENT: case VALUE_TUPLE_SIZE: - if (evaluate_type(node->first, &type)) + if (evaluate_type(machine, node->first, &type)) return 1; *out = type.kind == KIND_ARRAY ? type.number : 0; return 0; - case VALUE_INTEGRAL_CONSTANT: return evaluate_value(node->first, out); + case VALUE_INTEGRAL_CONSTANT: return evaluate_value(machine, node->first, out); + case VALUE_VARIABLE: + variable = find_variable(machine, node->name); + if (variable == NULL) + return complain(node, "that name was never declared"); + + *out = variable->value; + return 0; case VALUE_CONDITIONAL: - if (evaluate_condition(node->first, &truth)) + if (evaluate_condition(machine, node->first, &truth)) return 1; - return evaluate_value(truth ? node->second : node->third, out); + return evaluate_value(machine, truth ? node->second : node->third, out); default: break; } @@ -74,7 +118,7 @@ static int evaluate_value(const struct Node* node, int64_t* out) return 1; } -static int evaluate_type(const struct Node* node, struct Type* out) +static int evaluate_type(struct Machine* machine, const struct Node* node, struct Type* out) { out->kind = KIND_VOID; out->number = 0; @@ -86,18 +130,19 @@ static int evaluate_type(const struct Node* node, struct Type* out) case TYPE_INT32: out->kind = KIND_INT32; return 0; case TYPE_BYTE: out->kind = KIND_BYTE; return 0; case TYPE_SIZE: out->kind = KIND_SIZE; return 0; - case TYPE_REMOVE_CV: return evaluate_type(node->first, out); + case TYPE_REMOVE_CV: return evaluate_type(machine, node->first, out); case TYPE_ARRAY: - if (evaluate_type(node->first, &element) || evaluate_value(node->second, &out->number)) + if (evaluate_type(machine, node->first, &element) || + evaluate_value(machine, node->second, &out->number)) return 1; out->kind = KIND_ARRAY; return 0; case TYPE_CONDITIONAL: - if (evaluate_condition(node->first, &truth)) + if (evaluate_condition(machine, node->first, &truth)) return 1; - return evaluate_type(truth ? node->second : node->third, out); + return evaluate_type(machine, truth ? node->second : node->third, out); case TYPE_DECLTYPE: - if (evaluate_value(node->first, &out->number)) + if (evaluate_value(machine, node->first, &out->number)) return 1; out->kind = KIND_VALUE; return 0; @@ -113,7 +158,7 @@ static bool same_type(const struct Type* left, const struct Type* right) return left->kind == right->kind && left->number == right->number; } -static int evaluate_condition(const struct Node* node, bool* out) +static int evaluate_condition(struct Machine* machine, const struct Node* node, bool* out) { int64_t left = 0; int64_t right = 0; @@ -125,19 +170,20 @@ static int evaluate_condition(const struct Node* node, bool* out) case COND_TRUE: *out = true; return 0; case COND_FALSE: return 0; case COND_IS_SAME: - if (evaluate_type(node->first, &left_type) || evaluate_type(node->second, &right_type)) + if (evaluate_type(machine, node->first, &left_type) || + evaluate_type(machine, node->second, &right_type)) return 1; *out = same_type(&left_type, &right_type); return 0; case COND_EQUAL: - if (evaluate_operands(node, &left, &right)) + if (evaluate_operands(machine, node, &left, &right)) return 1; *out = left == right; return 0; case COND_LESS: - if (evaluate_operands(node, &left, &right)) + if (evaluate_operands(machine, node, &left, &right)) return 1; *out = left < right; @@ -149,10 +195,37 @@ static int evaluate_condition(const struct Node* node, bool* out) return 1; } -static enum RunStatus emit(const struct Node* node) +static enum RunStatus declare(struct Machine* machine, const struct Node* node) +{ + if (find_variable(machine, node->name) != NULL) + { + (void)complain(node, "already declared, and there is no changing that"); + return RUN_FAILED; + } + + struct Type type; + if (evaluate_type(machine, node->first, &type)) + return RUN_FAILED; + + if (type.kind != KIND_VALUE) + { + (void)complain(node, "that type carries no value, decltype something"); + return RUN_FAILED; + } + + if (!bind_variable(machine, node->name, type.number)) + { + (void)complain(node, "too many variables, this was never meant to scale"); + return RUN_FAILED; + } + + return RUN_DONE; +} + +static enum RunStatus emit(struct Machine* machine, const struct Node* node) { struct Type type; - if (evaluate_type(node->first, &type)) + if (evaluate_type(machine, node->first, &type)) return RUN_FAILED; switch (type.kind) @@ -168,10 +241,10 @@ static enum RunStatus emit(const struct Node* node) return RUN_DONE; } -static enum RunStatus static_assert_statement(const struct Node* node) +static enum RunStatus static_assert_statement(struct Machine* machine, const struct Node* node) { bool truth = false; - if (evaluate_condition(node->first, &truth)) + if (evaluate_condition(machine, node->first, &truth)) return RUN_FAILED; if (!truth) @@ -183,12 +256,13 @@ static enum RunStatus static_assert_statement(const struct Node* node) return RUN_DONE; } -static enum RunStatus execute_one(const struct Node* node) +static enum RunStatus execute_one(struct Machine* machine, const struct Node* node) { switch (node->kind) { - case STMT_EMIT: return emit(node); - case STMT_STATIC_ASSERT: return static_assert_statement(node); + case STMT_DECLARE: return declare(machine, node); + case STMT_EMIT: return emit(machine, node); + case STMT_STATIC_ASSERT: return static_assert_statement(machine, node); default: break; } @@ -196,11 +270,11 @@ static enum RunStatus execute_one(const struct Node* node) return RUN_FAILED; } -enum RunStatus execute(const struct Node* statement) +enum RunStatus execute(struct Machine* machine, const struct Node* statement) { while (statement != NULL) { - enum RunStatus status = execute_one(statement); + enum RunStatus status = execute_one(machine, statement); if (status != RUN_DONE) return status; |
