diff --git a/exercises/04/vslc/src/tree.c b/exercises/04/vslc/src/tree.c index a385870..60d40fb 100644 --- a/exercises/04/vslc/src/tree.c +++ b/exercises/04/vslc/src/tree.c @@ -12,6 +12,10 @@ tree_print(node_t* root, stem head); static void destroy_subtree ( node_t *discard ); +static void prune_children(node_t **simplified, node_t *root); +static void resolve_constant_expressions(node_t **simplified, node_t *root); +static void flatten(node_t **simplified, node_t *root); + /* External interface */ void @@ -154,18 +158,71 @@ destroy_subtree ( node_t *discard ) } } + +static void +flatten(node_t **simplified, node_t *root) +{ + /* This will flatten left-expanded lists */ + if (!root) + return; + + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + flatten(&root->children[i], root->children[i]); + + node_t **new_children, *result = root; + switch (root->type) + { + case GLOBAL_LIST: + case STATEMENT_LIST: + case PRINT_LIST: + case EXPRESSION_LIST: + case VARIABLE_LIST: + case DECLARATION_LIST: + // Check if node have more than two children + if (root->n_children < 2) + break; + + result = root->children[0]; + result->n_children++; + + // Realloc the array of children to the new size + if (!(new_children = realloc(result->children, result->n_children * sizeof(node_t*)))) + break; + // if successs, insert the new array + result->children = new_children; + + // Insert child at the end + result->children[result->n_children - 1] = root->children[1]; + + node_finalize(root); + break; + } + + *simplified = result; +} + + static void prune_children(node_t **simplified, node_t *root) { if (!root) return; + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + prune_children(&root->children[i], root->children[i]); + node_t *result = root; switch (root->type) { + case PROGRAM: case GLOBAL: //case ARGUMENT_LIST: // For this to work, need to change order of operations //case PARAMETER_LIST: // For this to work, need to change order of operations + //case VARIABLE_LIST: + //case EXPRESSION_LIST: + case DECLARATION: case STATEMENT: case PRINT_ITEM: case PRINT_STATEMENT: @@ -189,6 +246,10 @@ resolve_constant_expressions(node_t **simplified, node_t *root) if (!root) return; + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + resolve_constant_expressions(&root->children[i], root->children[i]); + if (root->type != EXPRESSION) return; @@ -239,6 +300,7 @@ resolve_constant_expressions(node_t **simplified, node_t *root) switch (*(char*)root->data) { + /* Assignments */ case '|': *lhs |= *rhs; break; case '^': *lhs ^= *rhs; break; case '&': *lhs &= *rhs; break; @@ -258,57 +320,80 @@ resolve_constant_expressions(node_t **simplified, node_t *root) *simplified = result; } + static void -flatten(node_t **simplified, node_t *root) +resolve_constant_relations( node_t** simplified, node_t* root) { - /* This will flatten left-expanded lists */ if (!root) return; - node_t **new_children, *result = root; - switch (root->type) + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + resolve_constant_relations(&root->children[i], root->children[i]); + + if (root->type != RELATION)//|| root->type != RELATION) + return; + + node_t *result = root; + + if (root->n_children != 2) + return; + + // Both children must be constant numbers + if (root->children[0]->type != NUMBER_DATA || + root->children[1]->type != NUMBER_DATA) + return; + + // Check if children does not contain null pointers + if (!root->children[0]->data) + return; + if (!root->children[1]->data) + return; + + // Check if data field is not null pointer + if (!root->data) + return; + + result = root->children[0]; + int64_t + *lhs = result->data, + *rhs = root->children[1]->data; + + switch (*(char*)root->data) { - case GLOBAL_LIST: - case STATEMENT_LIST: - case PRINT_LIST: - case EXPRESSION_LIST: - case VARIABLE_LIST: - case DECLARATION_LIST: - // Check if node have more than two children - if (root->n_children < 2) - break; - - result = root->children[0]; - result->n_children++; - - // Realloc the array of children to the new size - if (!(new_children = realloc(result->children, result->n_children * sizeof(node_t*)))) - break; - // if successs, insert the new array - result->children = new_children; - - // Insert child at the end - result->children[result->n_children - 1] = root->children[1]; - - node_finalize(root); - break; + /* Relations */ + case '=': *lhs = (*lhs == *rhs); break; + case '<': *lhs = (*lhs < *rhs); break; + case '>': *lhs = (*lhs > *rhs); break; } + node_finalize(root->children[1]); + node_finalize(root); + *simplified = result; } + static void simplify_tree ( node_t **simplified, node_t *root ) { if (!root) return; - for (int i = 0; i < root->n_children; i++) - simplify_tree(&root->children[i], root->children[i]); + //for (int i = 0; i < root->n_children; i++) + // simplify_tree(&root->children[i], root->children[i]); + /* + Each of the functions do their operations recursivly. + This opens up for a lot more flexibility, like removing + variable list after it is flatten + */ + flatten(&root, root); prune_children(&root, root); resolve_constant_expressions(&root, root); - flatten(&root, root); + + // The following is experimental, will resolve the constant relations + resolve_constant_relations(&root, root); *simplified = root; }