diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 106 |
1 files changed, 106 insertions, 0 deletions
@@ -133,6 +133,9 @@ struct type *tgen_type(enum type_kind kind, void ast_append(struct ast **list, struct ast *elem) { + assert(list); + assert(elem); + struct ast *cur = *list; if (!cur) { *list = elem; @@ -145,6 +148,23 @@ void ast_append(struct ast **list, struct ast *elem) cur->n = elem; } +void type_append(struct type **list, struct type *elem) +{ + assert(list); + assert(elem); + + struct type *cur = *list; + if (!cur) { + *list = elem; + return; + } + + while (cur->n) + cur = cur->n; + + cur->n = elem; +} + struct ast *ast_prepend(struct ast *list, struct ast *elem) { elem->n = list; @@ -295,6 +315,41 @@ struct ast *clone_ast_list(struct ast *root) return new_root; } +struct type *clone_type(struct type *type) +{ + if (!type) + return NULL; + + struct type *new = create_empty_type(); + if (!new) + return NULL; + + new->k = type->k; + if (type->id && !(new->id = strdup(type->id))) + return NULL; + + if (type->t0 && !(new->t0 = clone_type_list(type->t0))) + return NULL; + + return new; +} + +struct type *clone_type_list(struct type *root) +{ + struct type *n = root, *new_root = NULL, *prev = NULL; + while (n) { + struct type *new = clone_type(n); + + if (prev) prev->n = new; + else new_root = new; + + prev = new; + n = n->n; + } + + return new_root; +} + int ast_visit(ast_callback_t before, ast_callback_t after, struct ast *n, void *d) { @@ -346,6 +401,17 @@ size_t ast_list_len(struct ast *node) return count; } +size_t type_list_len(struct type *node) +{ + size_t count = 0; + while (node) { + count++; + node = node->n; + } + + return count; +} + struct ast *ast_last(struct ast *list) { if (!list) @@ -482,3 +548,43 @@ void fix_closures(struct ast *root) root = next; } } + +bool types_match(struct type *a, struct type *b) +{ + if (!a && !b) + return true; + + if (a && !b) + return false; + + if (!a && b) + return false; + + if (a->k != b->k) + return false; + + if (a->id && b->id && strcmp(a->id, b->id) != 0) + return false; + + if (!type_lists_match(a->t0, b->t0)) + return false; + + return true; +} + +bool type_lists_match(struct type *al, struct type *bl) +{ + if (type_list_len(al) != type_list_len(bl)) + return false; + + struct type *a = al; + struct type *b = bl; + while (a && b) { + if (!types_match(a, b)) + return false; + + a = a->n; + b = b->n; + } + return true; +} |