hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 14:38:55 +0200
committerhachem <im@hachem.wtf>2026-09-19 14:38:55 +0200
commitb79902cd36b2c5b54bbf0f07078fc528754977b2 (patch)
tree0f3baa55b58831c46c7631619f76eef5cb371f71 /eval.c
parent7160bdb390ef1c9bdcfb0c075b33be39d62860f3 (diff)
feat: variables and shi
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c140
1 files changed, 107 insertions, 33 deletions
diff --git a/eval.c b/eval.c
index b0ad454..fc6e6d7 100644
--- a/eval.c
+++ b/eval.c
@@ -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;