hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/eval.c b/eval.c
index 170b122..d19d029 100644
--- a/eval.c
+++ b/eval.c
@@ -118,10 +118,53 @@ static int evaluate_value(struct Machine* machine, const struct Node* node, int6
return 1;
}
+// writes what a type looks like when emitted. true when it does not fit
+static bool render(const struct Type* type, char* buffer, size_t size)
+{
+ int written = 0;
+ switch (type->kind)
+ {
+ case KIND_VOID: written = snprintf(buffer, size, "%s", ""); break;
+ case KIND_INT32: written = snprintf(buffer, size, "int32_t"); break;
+ case KIND_BYTE: written = snprintf(buffer, size, "byte"); break;
+ case KIND_SIZE: written = snprintf(buffer, size, "size_t"); break;
+ case KIND_ARRAY:
+ written = snprintf(buffer, size, "array[%" PRId64 "]", type->number);
+ break;
+ case KIND_CHAR: written = snprintf(buffer, size, "char"); break;
+ case KIND_CHAR_CONSTANT: written = snprintf(buffer, size, "%c", (char)type->number); break;
+ case KIND_VALUE: written = snprintf(buffer, size, "%" PRId64, type->number); break;
+ case KIND_TUPLE: written = snprintf(buffer, size, "%s", type->text); break;
+ }
+
+ return written < 0 || (size_t)written >= size;
+}
+
+// a tuple says everything its elements say, in order
+static int evaluate_tuple(struct Machine* machine, const struct Node* node, struct Type* out)
+{
+ out->kind = KIND_TUPLE;
+ size_t used = 0;
+ for (const struct Node* element = node->first; element != NULL; element = element->next)
+ {
+ struct Type inner;
+ if (evaluate_type(machine, element, &inner))
+ return 1;
+
+ if (render(&inner, out->text + used, sizeof out->text - used))
+ return complain(node, "that tuple is too much to say in one breath");
+
+ used = strlen(out->text);
+ }
+
+ return 0;
+}
+
static int evaluate_type(struct Machine* machine, const struct Node* node, struct Type* out)
{
out->kind = KIND_VOID;
out->number = 0;
+ out->text[0] = '\0';
struct Type element;
bool truth = false;
switch (node->kind)
@@ -131,6 +174,7 @@ static int evaluate_type(struct Machine* machine, const struct Node* node, struc
case TYPE_BYTE: out->kind = KIND_BYTE; return 0;
case TYPE_SIZE: out->kind = KIND_SIZE; return 0;
case TYPE_CHAR: out->kind = KIND_CHAR; return 0;
+ case TYPE_TUPLE: return evaluate_tuple(machine, node, out);
case TYPE_CHAR_CONSTANT:
if (evaluate_value(machine, node->first, &out->number))
return 1;
@@ -162,7 +206,8 @@ static int evaluate_type(struct Machine* machine, const struct Node* node, struc
static bool same_type(const struct Type* left, const struct Type* right)
{
- return left->kind == right->kind && left->number == right->number;
+ return left->kind == right->kind && left->number == right->number &&
+ strcmp(left->text, right->text) == 0;
}
static int evaluate_condition(struct Machine* machine, const struct Node* node, bool* out)
@@ -248,18 +293,18 @@ static enum RunStatus emit(struct Machine* machine, const struct Node* node)
if (evaluate_type(machine, node->first, &type))
return RUN_FAILED;
- switch (type.kind)
+ // void says nothing, not even a newline. everything else says its piece and ends the line
+ if (type.kind == KIND_VOID)
+ return RUN_DONE;
+
+ char text[TEXT_LENGTH_MAX + 1];
+ if (render(&type, text, sizeof text))
{
- case KIND_VOID: break;
- case KIND_INT32: (void)printf("int32_t\n"); break;
- case KIND_BYTE: (void)printf("byte\n"); break;
- case KIND_SIZE: (void)printf("size_t\n"); break;
- case KIND_ARRAY: (void)printf("array[%" PRId64 "]\n", type.number); break;
- case KIND_CHAR: (void)printf("char\n"); break;
- case KIND_CHAR_CONSTANT: (void)printf("%c\n", (char)type.number); break;
- case KIND_VALUE: (void)printf("%" PRId64 "\n", type.number); break;
+ (void)complain(node, "that is too much to say in one breath");
+ return RUN_FAILED;
}
+ (void)printf("%s\n", text);
return RUN_DONE;
}