From 96115b347e480c9adfa177f045c9d7033c637811 Mon Sep 17 00:00:00 2001 From: samsonium Date: Sat, 10 Oct 2026 03:56:00 +0300 Subject: [PATCH] feat: implement file writer --- CMakeLists.txt | 1 + include/compiler/fzl_writer.h | 25 ++++++++++++ src/compiler/fzl_writer.c | 72 +++++++++++++++++++++++++++++++++++ src/compiler/main.c | 41 +++++++++++++++++++- 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 include/compiler/fzl_writer.h create mode 100644 src/compiler/fzl_writer.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b60a09..0013498 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ add_executable(fzc src/compiler/fzl_parser.c src/compiler/fzl_debug.c src/compiler/fzl_walker.c + src/compiler/fzl_writer.c src/compiler/utils/fzl_const_pool.c src/compiler/main.c) diff --git a/include/compiler/fzl_writer.h b/include/compiler/fzl_writer.h new file mode 100644 index 0000000..f8184fd --- /dev/null +++ b/include/compiler/fzl_writer.h @@ -0,0 +1,25 @@ +#ifndef FZL_WRITER_H +#define FZL_WRITER_H + +#include +#include + +// File writer descriptor +typedef struct +{ + const char *filepath; +} fzl_writer_t; + +// Allocate writer +fzl_writer_t *fzl_mkwriter(const char *filepath); + +// Write out a file +int fzl_write(fzl_writer_t *writer, fzl_walker_t *walker); + +// Get last writer error message +char *fzl_writer_geterror(); + +// Free writer +void fzl_freewriter(fzl_writer_t *writer); + +#endif // FZL_WRITER_H diff --git a/src/compiler/fzl_writer.c b/src/compiler/fzl_writer.c new file mode 100644 index 0000000..22ec471 --- /dev/null +++ b/src/compiler/fzl_writer.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +char wrlast_err[256]; + +fzl_writer_t *fzl_mkwriter(const char *filepath) +{ + if (strlen(filepath) < 1) + return NULL; + + fzl_writer_t *writer = malloc(sizeof(fzl_writer_t)); + if (!writer) + return NULL; + + writer->filepath = filepath; + + return writer; +} + +int fzl_write(fzl_writer_t *writer, fzl_walker_t *walker) +{ + if (!writer || !walker) + return -1; + + FILE *fp = fopen(writer->filepath, "wb"); + if (!fp) + { + snprintf(wrlast_err, sizeof(wrlast_err), "failed to open '%s' to write", + writer->filepath); + return -1; + } + + const char hdr[5] = {'F', 'Z', 'L', 0x0, 0x1}; + fwrite(hdr, sizeof(char), 5, fp); + fwrite(&walker->consts->size, sizeof(size_t), 1, fp); + fwrite(&walker->op_count, sizeof(size_t), 1, fp); + + for (size_t i = 0; i < walker->consts->size; i++) + { + fzl_const_t c = walker->consts->array[i]; + fwrite(&c.type, sizeof(fzl_consttype_t), 1, fp); + + if (c.type == FZL_CONSTTYPE_STRING) + { + size_t strlen = c.as.string.length; + fwrite(&c.as.string.length, sizeof(size_t), 1, fp); + fwrite(c.as.string.chars, sizeof(char), strlen, fp); + } + } + + if (walker->op_count > 0) + fwrite(walker->ops, sizeof(uint64_t), walker->op_count, fp); + + fclose(fp); + + return 0; +} + +char *fzl_writer_geterror() { return wrlast_err; } + +void fzl_freewriter(fzl_writer_t *writer) +{ + if (!writer) + return; + + free(writer); +} diff --git a/src/compiler/main.c b/src/compiler/main.c index 3407ec0..46c0689 100644 --- a/src/compiler/main.c +++ b/src/compiler/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -11,6 +12,7 @@ typedef struct { char *filepath; + char *outpath; bool verbose; bool help; } build_args_t; @@ -32,6 +34,7 @@ build_args_t *getargs(int argc, char **argv) return NULL; args->filepath = NULL; + args->outpath = NULL; args->verbose = false; args->help = false; @@ -53,6 +56,15 @@ build_args_t *getargs(int argc, char **argv) { args->verbose = true; } + else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--out") == 0) + { + if (!argv[i + 1] || argv[i + 1][0] == '-') + { + printf("Error: file path is not specified.\n"); + return NULL; + } + args->outpath = argv[++i]; + } else { printf("Error: unknown argument '%s'\n", argv[i]); @@ -156,7 +168,8 @@ int main(int argc, char **argv) { printf("ok!\n"); fzl_debug_print_ast(parser->root); - printf("-> walking AST..."); + printf("> building\n"); + printf("-> walking AST...\n"); } fzl_walker_t *walker = fzl_mkwalker(parser->root); @@ -178,13 +191,39 @@ int main(int argc, char **argv) printf("--> Ops:\n"); for (size_t i = 0; i < walker->op_count; i++) printf("---> %lu\n", walker->ops[i]); + + printf("-> preparing final write\n"); } + char outpath[256]; + if (args->outpath) + strcpy(outpath, args->outpath); + else + strcpy(outpath, "a.fzlc"); + + if (args->verbose) + { + printf("-> output file path is: %s", outpath); + printf("-> writing file..."); + } + + fzl_writer_t *writer = fzl_mkwriter(outpath); + result = fzl_write(writer, walker); + if (result != 0) + { + printf("Error: %s\n", fzl_writer_geterror()); + return -1; + } + + if (args->verbose) + printf("ok!\n"); + free(args); fzl_freereader(rd); fzl_freeparser(parser); fzl_freeast(parser->root); fzl_freewalker(walker); + fzl_freewriter(writer); printf("done.\n"); return 0;