From cd38f358d4f3a5d5437dca9c69d8824ee7d1d18b Mon Sep 17 00:00:00 2001 From: Fredrik Robertsen Date: Mon, 23 Feb 2026 18:55:15 +0100 Subject: [PATCH] ps3: task 3 --- ps3/src/tree.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/ps3/src/tree.c b/ps3/src/tree.c index ae33280..c10e657 100644 --- a/ps3/src/tree.c +++ b/ps3/src/tree.c @@ -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; }