diff options
Diffstat (limited to 'eval.c')
| -rw-r--r-- | eval.c | 58 |
1 files changed, 54 insertions, 4 deletions
@@ -1,11 +1,13 @@ #include <assert.h> #include <inttypes.h> +#include <stdbool.h> #include <stdio.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 complain(const struct Node* node, const char* message) { @@ -26,6 +28,7 @@ static int evaluate_value(const struct Node* node, int64_t* out) int64_t left = 0; int64_t right = 0; struct Type type; + bool truth = false; switch (node->kind) { case VALUE_DIFFERENCE: @@ -56,11 +59,14 @@ static int evaluate_value(const struct Node* node, int64_t* out) case VALUE_TUPLE_SIZE: if (evaluate_type(node->first, &type)) return 1; - - // a non-array has no extent, so it gets zero, exactly like the real thing *out = type.kind == KIND_ARRAY ? type.number : 0; return 0; case VALUE_INTEGRAL_CONSTANT: return evaluate_value(node->first, out); + case VALUE_CONDITIONAL: + if (evaluate_condition(node->first, &truth)) + return 1; + + return evaluate_value(truth ? node->second : node->third, out); default: break; } @@ -73,6 +79,7 @@ static int evaluate_type(const struct Node* node, struct Type* out) out->kind = KIND_VOID; out->number = 0; struct Type element; + bool truth = false; switch (node->kind) { case TYPE_VOID: return 0; @@ -81,12 +88,14 @@ static int evaluate_type(const struct Node* node, struct Type* out) case TYPE_SIZE: out->kind = KIND_SIZE; return 0; case TYPE_REMOVE_CV: return evaluate_type(node->first, out); case TYPE_ARRAY: - // the element type is evaluated for its side of the bargain, then forgotten if (evaluate_type(node->first, &element) || evaluate_value(node->second, &out->number)) return 1; - out->kind = KIND_ARRAY; return 0; + case TYPE_CONDITIONAL: + if (evaluate_condition(node->first, &truth)) + return 1; + return evaluate_type(truth ? node->second : node->third, out); case TYPE_DECLTYPE: if (evaluate_value(node->first, &out->number)) return 1; @@ -99,6 +108,47 @@ static int evaluate_type(const struct Node* node, struct Type* out) return 1; } +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) +{ + int64_t left = 0; + int64_t right = 0; + struct Type left_type; + struct Type right_type; + *out = false; + switch (node->kind) + { + 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)) + return 1; + + *out = same_type(&left_type, &right_type); + return 0; + case COND_EQUAL: + if (evaluate_operands(node, &left, &right)) + return 1; + + *out = left == right; + return 0; + case COND_LESS: + if (evaluate_operands(node, &left, &right)) + return 1; + + *out = left < right; + return 0; + default: break; + } + + assert(!"the parser handed a non-condition where a condition goes"); + return 1; +} + static enum RunStatus emit(const struct Node* node) { struct Type type; |
