diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-05-07 21:22:38 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-05-07 21:22:38 +0300 |
commit | 0e0c41af58a0f4ec5a39ce77822de71e5523fcba (patch) | |
tree | 4a02b2f93e61411cbfc6084b0855dba51b326cd9 /src/rewrite.c | |
parent | 1fadcec6d7b26d34edf3b5b3a293deea0edb4139 (diff) | |
download | fwd-0e0c41af58a0f4ec5a39ce77822de71e5523fcba.tar.gz fwd-0e0c41af58a0f4ec5a39ce77822de71e5523fcba.zip |
implement enough type analysis for vector examplegnc
+ Big commit, scary
+ Some details still a bit up in the air, mainly about move checking
structure member access ('register' types are freely copied I guess,
same as in rust? How about user types?)
Diffstat (limited to 'src/rewrite.c')
-rw-r--r-- | src/rewrite.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/rewrite.c b/src/rewrite.c new file mode 100644 index 0000000..e3cea01 --- /dev/null +++ b/src/rewrite.c @@ -0,0 +1,96 @@ +#include <fwd/rewrite.h> +#include <stddef.h> +#include <stdlib.h> + +struct type_helper { + char *orig; + char *new; +}; + +/* types are simple enough (for now) that this works fine */ +static int rewrite_type_ids(struct type *type, char *orig, char *new) +{ + if (type->k == TYPE_ID && strcmp(type->id, orig) == 0) { + char *r = strdup(new); + free(type->id); + type->id = r; + } + + if (type->t0 && rewrite_type_ids(type->t0, orig, new)) + return -1; + + if (type->n && rewrite_type_ids(type->n, orig, new)) + return -1; + + return 0; +} + +static int rewrite_type_visit(struct ast *node, struct type_helper *helper) +{ + if (node->t2) + return rewrite_type_ids(node->t2, helper->orig, helper->new); + + return 0; +} + +int rewrite_types(struct ast *node, char *orig, char *new) +{ + struct type_helper helper = {.orig = orig, .new = new}; + return ast_visit((ast_callback_t)rewrite_type_visit, NULL, node, &helper); +} + +/* not the fastest thing in the world but should work well enough for now */ +static char *rewrite_hole(char *old, char *new) +{ + /* skip "<>" */ + size_t on = strlen(old) - 2; + size_t nn = strlen(new); + + /* +1 for null terminator */ + char *r = malloc(on + nn + 1); + + memcpy(r, new, nn); + + /* +2 to skip "<>", +1 for null terminator */ + memcpy(r + nn, old + 2, on + 1); + return r; +} + +static int rewrite_type_holes(struct type *type, char *new) +{ + if (type->id && strncmp(type->id, "<>", 2) == 0) { + char *r = rewrite_hole(type->id, new); + free(type->id); + type->id = r; + } + + if (type->t0 && rewrite_type_holes(type->t0, new)) + return -1; + + if (type->n && rewrite_type_holes(type->n, new)) + return -1; + + return 0; +} + +static int rewrite_holes_visit(struct ast *node, char *new) +{ + if (node->k == AST_CONST_STR) + return 0; + + if (node->s && strncmp(node->s, "<>", 2) == 0) { + char *r = rewrite_hole(node->s, new); + free(node->s); + node->s = r; + } + + if (node->t2 && rewrite_type_holes(node->t2, new)) + return -1; + + return 0; +} + +int rewrite_holes(struct ast *node, char *new) +{ + return ast_visit((ast_callback_t)rewrite_holes_visit, NULL, node, new); +} |