From f91af58c4300148b70a98ae2ec47ee40cc8b0c80 Mon Sep 17 00:00:00 2001
From: overflowerror <mail@overflowerror.com>
Date: Fri, 26 Apr 2024 14:54:08 +0200
Subject: [PATCH] refactor: Moved macro stuff to builtins

---
 compiler/Makefile                           |  6 ++++--
 compiler/obj/builtins/.gitignore            |  0
 compiler/src/builtins/builtins.c            | 24 +++++++++++++++++++++
 compiler/src/builtins/builtins.h            | 13 +++++++++++
 compiler/src/{macros => builtins}/numbers.c |  9 ++++----
 compiler/src/codegen.c                      | 15 ++++++++++---
 6 files changed, 58 insertions(+), 9 deletions(-)
 create mode 100644 compiler/obj/builtins/.gitignore
 create mode 100644 compiler/src/builtins/builtins.c
 create mode 100644 compiler/src/builtins/builtins.h
 rename compiler/src/{macros => builtins}/numbers.c (93%)

diff --git a/compiler/Makefile b/compiler/Makefile
index dbb0793..85279ad 100644
--- a/compiler/Makefile
+++ b/compiler/Makefile
@@ -9,9 +9,10 @@ LEXFLAGS =
 MAKE     = make
 
 
-PLUGINS  = obj/macros/numbers.o
+PLUGINS  =
+BUILTINS = obj/builtins/builtins.o obj/builtins/numbers.o
 OBJS     = obj/lex.yy.o obj/y.tab.o obj/codegen.o obj/ast.o obj/band.o \
-           obj/plugins.o obj/scope.o $(PLUGINS) obj/main.o
+           obj/plugins.o obj/scope.o $(PLUGINS) $(BUILTINS) obj/main.o
 DEPS     = $(OBJS:%.o=%.d)
 
 -include $(DEPS)
@@ -38,6 +39,7 @@ macrofuck: $(OBJS) ../common/common.a
 	cd ../common/ && $(MAKE) common.a
 
 test: macrofuck FORCE
+	cd ../common/ && $(MAKE) test
 	./test/tests.sh "./macrofuck"
 
 FORCE: ;
diff --git a/compiler/obj/builtins/.gitignore b/compiler/obj/builtins/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/compiler/src/builtins/builtins.c b/compiler/src/builtins/builtins.c
new file mode 100644
index 0000000..fc83ebe
--- /dev/null
+++ b/compiler/src/builtins/builtins.c
@@ -0,0 +1,24 @@
+#include <string.h>
+
+#include "builtins.h"
+
+#define decl(n) region_t* n(FILE*, scope_t*, size_t, region_t**)
+
+decl(to_str);
+
+static struct builtin_list_item {
+    const char* name;
+    builtin_t function;
+} builtins[] = {
+    {"to_str", to_str },
+};
+
+builtin_t find_builtin(const char* name) {
+    for (size_t i = 0; i < sizeof(builtins) / sizeof(struct builtin_list_item); i++) {
+        if (strcmp(name, builtins[i].name) == 0) {
+            return builtins[i].function;
+        }
+    }
+
+    return NULL;
+}
diff --git a/compiler/src/builtins/builtins.h b/compiler/src/builtins/builtins.h
new file mode 100644
index 0000000..7a702ec
--- /dev/null
+++ b/compiler/src/builtins/builtins.h
@@ -0,0 +1,13 @@
+#ifndef BUILTINS_H
+#define BUILTINS_H
+
+#include <stdio.h>
+
+#include "../band.h"
+#include "../scope.h"
+
+typedef region_t* (*builtin_t)(FILE*, scope_t*, size_t, region_t**);
+
+builtin_t find_builtin(const char*);
+
+#endif
diff --git a/compiler/src/macros/numbers.c b/compiler/src/builtins/numbers.c
similarity index 93%
rename from compiler/src/macros/numbers.c
rename to compiler/src/builtins/numbers.c
index 1987a57..b39a72a 100644
--- a/compiler/src/macros/numbers.c
+++ b/compiler/src/builtins/numbers.c
@@ -5,12 +5,13 @@
 #include "../scope.h"
 #include "../codegen.h"
 
-extern region_t* to_str(FILE* out, scope_t* scope, const char* _arg) {
-    region_t* arg = scope_get(scope, _arg);
-    if (!arg) {
-        panic("argument has to be a variable");
+extern region_t* to_str(FILE* out, scope_t* scope, size_t argc, region_t** argv) {
+    if (argc != 1) {
+        panic("to_str() needs exactly 1 argument");
     }
 
+    region_t* arg = argv[0];
+
     region_t* str = scope_add_tmp(scope, 3);
     for (size_t i = 0; i < str->size; i++) {
         move_offset(str, i); reset();
diff --git a/compiler/src/codegen.c b/compiler/src/codegen.c
index 45aa06c..b6cc444 100644
--- a/compiler/src/codegen.c
+++ b/compiler/src/codegen.c
@@ -8,7 +8,7 @@
 #include "ast.h"
 #include "band.h"
 #include "scope.h"
-#include "plugins.h"
+#include "builtins/builtins.h"
 
 
 void _move_to(FILE* out, scope_t* scope, size_t target) {
@@ -114,8 +114,17 @@ region_t* codegen_variable_expr(FILE* _, scope_t* scope, struct variable_express
 }
 
 region_t* codegen_macro_expr(FILE* out, scope_t* scope, struct macro_expression expr) {
-    macro_t macro = find_macro(expr.id);
-    return macro(out, scope, expr.argument);
+    builtin_t macro = find_builtin(expr.id);
+    if (macro == NULL) {
+        panic("unable to find builtin");
+    }
+
+    region_t* arg = scope_get(scope, expr.argument);
+    if (arg == NULL) {
+        panic("argument has to be a variable");
+    }
+
+    return macro(out, scope, 1, &arg);
 }
 
 region_t* codegen_expr(FILE*, scope_t*, struct expression*);