ps3: task 3

This commit is contained in:
2026-02-23 18:55:15 +01:00
parent 5652421bc5
commit cd38f358d4

View File

@@ -1,4 +1,5 @@
#include "vslc.h"
#include "bool.h"
// Global root for abstract syntax tree
node_t* root;
@@ -132,12 +133,14 @@ static node_t* convert_operator(node_t* node)
assert(node->type == OPERATOR);
switch (node->data.operator) {
case "or":
free(node->data.operator);
node->data.operator = "?:";
node_t *new = node_create(NUMBER_LITERAL, 0);
new->data.number_literal = 0;
append_to_list_node(node, new);
break;
case "and":
free(node->data.operator);
node->data.operator = "?:";
node_t *new = node_create(NUMBER_LITERAL, 0);
new->data.number_literal = 1;
@@ -154,7 +157,111 @@ static node_t* convert_operator(node_t* node)
static node_t* constant_fold_operator(node_t* node)
{
assert(node->type == OPERATOR);
// TODO: Task 3: Implement this function
bool b = 1;
for (int i = 0; i < node->n_children; i++)
b &= node->children[i]->type == NUMBER_LITERAL;
if !b return;
node_t *a, *b, *c;
if (node->n_children == 1) {
a = node->children[0];
switch (node->data.operator) {
case "-":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = -a->data.number_literal;
break;
case "!":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = !a->data.number_literal;
break;
default:
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];
switch (node->data.operator) {
case "==":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal == b->data.number_literal;
break;
case "!=":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal != b->data.number_literal;
break;
case "<":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal < b->data.number_literal;
break;
case "<=":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal <= b->data.number_literal;
break;
case ">":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal > b->data.number_literal;
break;
case ">=":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal >= b->data.number_literal;
break;
case "+":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal + b->data.number_literal;
break;
case "-":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal - b->data.number_literal;
break;
case "*":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal * b->data.number_literal;
break;
case "/":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal / b->data.number_literal;
break;
default:
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];
switch (node->data.operator) {
case "?:":
free(node->data.operator);
node->type = NUMBER_LITERAL;
node->data.number_literal = a->data.number_literal ? b->data.number_literal : c->data.number_literal;
break;
default:
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;
}