aboutsummaryrefslogtreecommitdiff
path: root/interpreter/graphs.c
diff options
context:
space:
mode:
Diffstat (limited to 'interpreter/graphs.c')
-rw-r--r--interpreter/graphs.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/interpreter/graphs.c b/interpreter/graphs.c
new file mode 100644
index 0000000..34877a2
--- /dev/null
+++ b/interpreter/graphs.c
@@ -0,0 +1,134 @@
+#include "graphs.h"
+
+#include <string.h>
+
+#include "mem.h"
+
+void use_node(struct node* node, unsigned int count) {
+ if (!node)
+ return;
+
+ node->used_count += count;
+
+ if (node->kind == EXPR_LIST ||
+ node->kind == EXPR_TUPLE ||
+ node->kind == EXPR_APP) {
+ use_node(node->var1, count);
+ use_node(node->var2, count);
+ }
+}
+
+void free_node(struct node* node, unsigned free_first) {
+ if (!node)
+ return;
+
+ node->used_count--;
+
+ if (node->kind == EXPR_LIST ||
+ node->kind == EXPR_TUPLE ||
+ node->kind == EXPR_APP) {
+ free_node((struct node*) node->var1, 1);
+ free_node((struct node*) node->var2, 1);
+ }
+
+ if (node->used_count == 0) {
+ if (node->kind == EXPR_INT || node->kind == EXPR_NAME)
+ my_free(node->var1);
+
+ if (node->kind == EXPR_CODE)
+ my_free(node->var2);
+
+ if (free_first)
+ my_free(node);
+ }
+}
+
+nodes_array* push_node(nodes_array* nodes, struct node* node) {
+ unsigned int i;
+ for (i = 0; i < nodes->length && nodes->nodes[i]; i++);
+ if (nodes->nodes[i])
+ nodes = my_realloc(nodes, sizeof(nodes_array) +
+ 2 * nodes->length * sizeof(*node));
+ nodes->nodes[i] = node;
+ nodes->nodes[i + 1] = NULL;
+ return nodes;
+}
+
+void cpy_expression_to_node(struct node* dst, expression* src) {
+ if (!dst || !src)
+ return;
+
+ dst->kind = src->kind;
+ switch (src->kind) {
+ case EXPR_INT:
+ dst->var1 = my_calloc(1, sizeof(int));
+ *((int*) dst->var1) = *((int*) src->var1);
+ break;
+
+ case EXPR_NAME:
+ dst->var1 = my_calloc(1, 1 + strlen((char*) src->var1));
+ strcpy(dst->var1, src->var1);
+ break;
+
+ case EXPR_CODE:
+ dst->var1 = src->var1;
+ dst->var2 = my_calloc(1, sizeof(unsigned char));
+ *((unsigned char*) dst->var2) = *((unsigned char*) src->var2);
+ break;
+
+ case EXPR_LIST:
+ case EXPR_TUPLE:
+ case EXPR_APP:
+ dst->var1 = dst->var2 = NULL;
+ if (src->var1) {
+ dst->var1 = my_calloc(1, sizeof(struct node));
+ cpy_expression_to_node(dst->var1, src->var1);
+ }
+ if (src->var2) {
+ dst->var2 = my_calloc(1, sizeof(struct node));
+ cpy_expression_to_node(dst->var2, src->var2);
+ }
+ }
+
+ dst->used_count = 1;
+}
+
+void cpy_node_to_expression(expression* dst, struct node* src) {
+ if (!dst || !src)
+ return;
+
+ free_expression(dst);
+ dst->is_strict = 0;
+
+ dst->kind = src->kind;
+ switch (src->kind) {
+ case EXPR_INT:
+ dst->var1 = my_calloc(1, sizeof(int));
+ *((int*) dst->var1) = *((int*) src->var1);
+ break;
+
+ case EXPR_NAME:
+ dst->var1 = my_calloc(1, 1 + strlen((char*) src->var1));
+ strcpy(dst->var1, src->var1);
+ break;
+
+ case EXPR_CODE:
+ dst->var1 = src->var1;
+ dst->var2 = my_calloc(1, sizeof(unsigned char));
+ *((unsigned char*) dst->var2) = *((unsigned char*) src->var2);
+ break;
+
+ case EXPR_LIST:
+ case EXPR_TUPLE:
+ case EXPR_APP:
+ dst->var1 = dst->var2 = NULL;
+ if (src->var1) {
+ dst->var1 = my_calloc(1, sizeof(expression));
+ cpy_node_to_expression(dst->var1, src->var1);
+ }
+ if (src->var2) {
+ dst->var2 = my_calloc(1, sizeof(expression));
+ cpy_node_to_expression(dst->var2, src->var2);
+ }
+ }
+}