constant folding works

This commit is contained in:
2026-03-01 13:30:31 +01:00
parent cd8bb29524
commit c1bc4db814
+23 -49
View File
@@ -131,8 +131,8 @@ static void node_print(node_t* node, int nesting)
static node_t* convert_operator(node_t* node)
{
assert(node->type == OPERATOR);
assert(node->children[0] && node->children[1]);
if (strcmp(node->data.operator, "or") == 0) {
assert(node->children[0] && node->children[1]);
node_t *one = node_create(NUMBER_LITERAL, 0);
one->data.number_literal = 1;
node_t *converted_op = node_create(OPERATOR, 3, node->children[0], one, node->children[1]);
@@ -140,6 +140,7 @@ static node_t* convert_operator(node_t* node)
node_finalize(node);
node = converted_op;
} else if (strcmp(node->data.operator, "and") == 0) {
assert(node->children[0] && node->children[1]);
node_t *zero = node_create(NUMBER_LITERAL, 0);
zero->data.number_literal = 0;
node_t *converted_op = node_create(OPERATOR, 3, node->children[0], node->children[1], zero);
@@ -158,92 +159,65 @@ static node_t* constant_fold_operator(node_t* node)
assert(node->type == OPERATOR);
for (int i = 0; i < node->n_children; i++)
assert(node->children[i]->type == NUMBER_LITERAL);
node_t *a, *b, *c;
node_t *a, *b, *c, *result;
if (node->n_children == 1) {
a = node->children[0];
result = node_create(NUMBER_LITERAL, 0);
if (strcmp(node->data.operator, "-") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = -a->data.number_literal;
result->data.number_literal = -a->data.number_literal;
} else if (strcmp(node->data.operator, "!") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = !a->data.number_literal;
result->data.number_literal = !a->data.number_literal;
} else {
fprintf(stderr, "folding: unexpected unary operator");
exit(1);
}
destroy_subtree(a);
} else if (node->n_children == 2) {
a = node->children[0];
b = node->children[1];
result = node_create(NUMBER_LITERAL, 0);
if (strcmp(node->data.operator, "==") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal == b->data.number_literal;
result->data.number_literal = a->data.number_literal == b->data.number_literal;
} else if (strcmp(node->data.operator, "!=") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal != b->data.number_literal;
result->data.number_literal = a->data.number_literal != b->data.number_literal;
} else if (strcmp(node->data.operator, "<") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal < b->data.number_literal;
result->data.number_literal = a->data.number_literal < b->data.number_literal;
} else if (strcmp(node->data.operator, "<=") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal <= b->data.number_literal;
result->data.number_literal = a->data.number_literal <= b->data.number_literal;
} else if (strcmp(node->data.operator, ">") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal > b->data.number_literal;
result->data.number_literal = a->data.number_literal > b->data.number_literal;
} else if (strcmp(node->data.operator, ">=") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal >= b->data.number_literal;
result->data.number_literal = a->data.number_literal >= b->data.number_literal;
} else if (strcmp(node->data.operator, "+") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal + b->data.number_literal;
result->data.number_literal = a->data.number_literal + b->data.number_literal;
} else if (strcmp(node->data.operator, "-") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal - b->data.number_literal;
result->data.number_literal = a->data.number_literal - b->data.number_literal;
} else if (strcmp(node->data.operator, "*") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal * b->data.number_literal;
result->data.number_literal = a->data.number_literal * b->data.number_literal;
} else if (strcmp(node->data.operator, "/") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal / b->data.number_literal;
result->data.number_literal = a->data.number_literal / b->data.number_literal;
} else {
fprintf(stderr, "folding: unexpected binary operator");
exit(1);
}
destroy_subtree(a);
destroy_subtree(b);
} else if (node->n_children == 3) {
a = node->children[0];
b = node->children[1];
c = node->children[2];
result = node_create(NUMBER_LITERAL, 0);
if (strcmp(node->data.operator, "?:") == 0) {
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal ? b->data.number_literal : c->data.number_literal;
result->data.number_literal = a->data.number_literal ? b->data.number_literal : c->data.number_literal;
} else {
fprintf(stderr, "folding: unexpected trinary operator");
exit(1);
}
destroy_subtree(a);
destroy_subtree(b);
destroy_subtree(c);
} else {
fprintf(stderr, "folding: unexpected number of children: %d", node->n_children);
}
return node;
destroy_subtree(node);
return result;
}
// Convert PRINTLN_STATEMENT into PRINT_STATEMENT by appending an extra "\n"