aboutsummaryrefslogtreecommitdiff
path: root/src/rewrite.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-05-07 21:22:38 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-05-07 21:22:38 +0300
commit0e0c41af58a0f4ec5a39ce77822de71e5523fcba (patch)
tree4a02b2f93e61411cbfc6084b0855dba51b326cd9 /src/rewrite.c
parent1fadcec6d7b26d34edf3b5b3a293deea0edb4139 (diff)
downloadfwd-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.c96
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);
+}