From e6c3c55179e4dd310d6c06e2fcd2a69291d6ba13 Mon Sep 17 00:00:00 2001
From: David Gonzalez Martin <davidgmbb@gmail.com>
Date: Fri, 21 Feb 2025 20:13:25 -0600
Subject: [PATCH] Structure main program properly

---
 .gitignore       |  1 +
 build.zig        |  8 +++++++-
 src/compiler.bbb |  4 ++++
 src/lib.zig      | 37 ++++++++++++++++++++++++++++++++++++-
 src/main.zig     | 41 +++++++++++++++++++++++++++++++++++++++--
 5 files changed, 87 insertions(+), 4 deletions(-)
 create mode 100644 src/compiler.bbb

diff --git a/.gitignore b/.gitignore
index 291266b..d96d990 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@ imgui.ini
 /.gdb_history
 /.zig-cache/
 /zig-out/
+/bb-cache/
diff --git a/build.zig b/build.zig
index 0fca90e..9518d1b 100644
--- a/build.zig
+++ b/build.zig
@@ -274,7 +274,13 @@ fn debug_binary(b: *std.Build, exe: *std.Build.Step.Compile) *std.Build.Step.Run
     run_step.addArg("gdb");
     run_step.addArg("-ex");
     run_step.addArg("r");
-    run_step.addArtifactArg(exe);
+    if (b.args) |args| {
+        run_step.addArg("--args");
+        run_step.addArtifactArg(exe);
+        run_step.addArgs(args);
+    } else {
+        run_step.addArtifactArg(exe);
+    }
 
     return run_step;
 }
diff --git a/src/compiler.bbb b/src/compiler.bbb
new file mode 100644
index 0000000..5ff19c1
--- /dev/null
+++ b/src/compiler.bbb
@@ -0,0 +1,4 @@
+[export] main = fn [cc(c)] () s32
+{
+    return 0;
+}
diff --git a/src/lib.zig b/src/lib.zig
index ecaa8d0..c396c39 100644
--- a/src/lib.zig
+++ b/src/lib.zig
@@ -279,6 +279,16 @@ pub const os = struct {
         }
     }
 
+    pub fn make_directory(path: [*:0]const u8) void {
+        switch (builtin.os.tag) {
+            .windows => @compileError("TODO"),
+            else => {
+                const result = posix.mkdir(path, 0o755);
+                _ = result;
+            },
+        }
+    }
+
     const linux = struct {
         pub const CPU_SETSIZE = 128;
         pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize;
@@ -409,6 +419,7 @@ pub const os = struct {
         extern "c" fn read(fd: system.FileDescriptor, pointer: [*]u8, byte_count: usize) isize;
         extern "c" fn write(fd: system.FileDescriptor, pointer: [*]const u8, byte_count: usize) isize;
         extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
+        extern "c" fn mkdir(path: [*:0]const u8, mode: mode_t) c_int;
 
         const mode_t = usize;
 
@@ -522,6 +533,29 @@ pub const string = struct {
         }
         return result;
     }
+
+    pub fn first_character(str: []const u8, ch: u8) ?usize {
+        for (str, 0..) |existing_ch, i| {
+            if (ch == existing_ch) {
+                return i;
+            }
+        }
+
+        return null;
+    }
+
+    pub fn last_character(str: []const u8, ch: u8) ?usize {
+        var i = str.len;
+        while (i > 0) {
+            i -= 1;
+
+            if (str[i] == ch) {
+                return i;
+            }
+        }
+
+        return null;
+    }
 };
 
 pub const cstring = struct {
@@ -2474,6 +2508,7 @@ pub const GlobalState = struct {
     thread_count: usize,
 
     pub var initialized = false;
+
     pub fn initialize() void {
         assert(!initialized);
         defer initialized = true;
@@ -2515,7 +2550,7 @@ pub fn print(format_string: [*:0]const u8, ...) callconv(.C) void {
     @cVaEnd(&args);
 }
 
-pub const print_string = print_string_stdout;
+pub const print_string = print_string_stderr;
 
 pub fn print_string_stdout(str: []const u8) void {
     os.get_stdout().write(str);
diff --git a/src/main.zig b/src/main.zig
index dd442bc..36a45d1 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,4 +1,5 @@
 const lib = @import("lib.zig");
+const os = lib.os;
 const llvm = @import("LLVM.zig");
 const converter = @import("converter.zig");
 const Arena = lib.Arena;
@@ -136,9 +137,45 @@ pub const panic = struct {
     }
 };
 
-var global_persistent_arena: *Arena = undefined;
+pub fn main(argc: c_int, argv: [*:null]const ?[*:0]const u8) callconv(.C) c_int {
+    if (argc != 2) {
+        lib.print_string("Failed to match argument count");
+        return 1;
+    }
+    const file_path_pointer = argv[1] orelse return 1;
+    const file_path = lib.cstring.to_slice(file_path_pointer);
+    if (file_path.len < 5) {
+        return 1;
+    }
 
-pub fn main() callconv(.C) c_int {
+    const extension_start = lib.string.last_character(file_path, '.') orelse return 1;
+    if (!lib.string.equal(file_path[extension_start..], ".bbb")) {
+        return 1;
+    }
+    const separator_index = lib.string.last_character(file_path, '/') orelse 0;
+    const base_start = separator_index + @intFromBool(separator_index != 0 or file_path[separator_index] == '/');
+    const base_name = file_path[base_start..extension_start];
+
+    lib.GlobalState.initialize();
+
+    const arena = lib.global.arena;
+
+    const build_dir = "bb-cache";
+    os.make_directory(build_dir);
+    const output_path_base = arena.join_string(&.{ build_dir, "/", base_name });
+    const output_object_path = arena.join_string(&.{ output_path_base, ".o" });
+    const output_executable_path = output_path_base;
+
+    const file_content = lib.file.read(arena, file_path);
+    converter.convert(.{
+        .executable = output_executable_path,
+        .object = output_object_path,
+        .name = base_name,
+        .build_mode = .debug_none,
+        .content = file_content,
+        .path = file_path,
+        .has_debug_info = 1,
+    });
     return 0;
 }