From 84572edb0d62c97d5957ecfe8930d9ddf08b3d7e Mon Sep 17 00:00:00 2001 From: samsonium Date: Thu, 5 Nov 2026 18:40:02 +0300 Subject: [PATCH] feat: implement extern libs data writing --- CMakeLists.txt | 5 ++ include/compiler/internals/writer.h | 16 ++++++ src/compiler/fzl_writer.c | 73 ++++++++++++++++++--------- src/compiler/writer/wr_consts.c | 25 +++++++++ src/compiler/writer/wr_extern_fns.c | 67 ++++++++++++++++++++++++ src/compiler/writer/wr_extern_libs.c | 30 +++++++++++ src/compiler/writer/wr_extern_types.c | 72 ++++++++++++++++++++++++++ src/compiler/writer/wr_ops.c | 14 +++++ 8 files changed, 279 insertions(+), 23 deletions(-) create mode 100644 include/compiler/internals/writer.h create mode 100644 src/compiler/writer/wr_consts.c create mode 100644 src/compiler/writer/wr_extern_fns.c create mode 100644 src/compiler/writer/wr_extern_libs.c create mode 100644 src/compiler/writer/wr_extern_types.c create mode 100644 src/compiler/writer/wr_ops.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d9ae82c..79901be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,11 @@ if (NOT FZL_SKIP_C) src/compiler/reader/rd_number.c src/compiler/reader/rd_string_literal.c src/compiler/reader/utility.c + src/compiler/writer/wr_consts.c + src/compiler/writer/wr_extern_fns.c + src/compiler/writer/wr_extern_libs.c + src/compiler/writer/wr_extern_types.c + src/compiler/writer/wr_ops.c src/compiler/fzl_analyzer.c src/compiler/fzl_debug.c src/compiler/fzl_gen.c diff --git a/include/compiler/internals/writer.h b/include/compiler/internals/writer.h new file mode 100644 index 0000000..a511ee8 --- /dev/null +++ b/include/compiler/internals/writer.h @@ -0,0 +1,16 @@ +#ifndef INTERNALS_WRITER_H +#define INTERNALS_WRITER_H + +#include +#include +#include +#include +#include + +bool wr_consts(FILE *fd, fzl_const_hash_pool_t *consts); +bool wr_extern_libs(FILE *fd, fzl_extern_lib_t *libs, size_t libs_count); +bool wr_extern_types(FILE *fd, fzl_extern_type_t *types, size_t types_count); +bool wr_extern_fns(FILE *fd, fzl_extern_fn_t *fns, size_t fns_count); +bool wr_ops(FILE *fd, size_t *ops, size_t ops_count); + +#endif // INTERNALS_WRITER_H diff --git a/src/compiler/fzl_writer.c b/src/compiler/fzl_writer.c index 527c90d..59013ae 100644 --- a/src/compiler/fzl_writer.c +++ b/src/compiler/fzl_writer.c @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include #include #include @@ -28,41 +30,66 @@ int fzl_write(fzl_writer_t *writer, fzl_gen_t *gen) if (!writer || !gen) return -1; - FILE *fp = fopen(writer->filepath, "wb"); - if (!fp) + FILE *fd = fopen(writer->filepath, "wb"); + if (!fd) { 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(&gen->consts->size, sizeof(size_t), 1, fp); - fwrite(&gen->extern_libs_count, sizeof(size_t), 1, fp); - fwrite(&gen->extern_types_count, sizeof(size_t), 1, fp); - fwrite(&gen->extern_fns_count, sizeof(size_t), 1, fp); - fwrite(&gen->ops_count, sizeof(size_t), 1, fp); + const char hdr[5] = {'F', 'Z', 'L', 0x0, 0x2}; + fwrite(hdr, sizeof(char), 5, fd); + fwrite(&gen->consts->size, sizeof(size_t), 1, fd); + fwrite(&gen->extern_libs_count, sizeof(size_t), 1, fd); + fwrite(&gen->extern_types_count, sizeof(size_t), 1, fd); + fwrite(&gen->extern_fns_count, sizeof(size_t), 1, fd); + fwrite(&gen->ops_count, sizeof(size_t), 1, fd); - for (size_t i = 0; i < gen->consts->size; i++) + bool result = wr_consts(fd, gen->consts); + if (!result) { - fzl_const_t c = gen->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); - } + snprintf(wrlast_err, sizeof(wrlast_err), "failed to write constants table"); + fclose(fd); + return -1; } - // TODO: write libs, types and functions + result = wr_extern_libs(fd, gen->extern_libs, gen->extern_libs_count); + if (!result) + { + snprintf(wrlast_err, sizeof(wrlast_err), + "failed to write external lib names"); + fclose(fd); + return -1; + } - if (gen->ops_count > 0) - fwrite(gen->ops, sizeof(uint64_t), gen->ops_count, fp); + result = wr_extern_types(fd, gen->extern_types, gen->extern_types_count); + if (!result) + { + snprintf(wrlast_err, sizeof(wrlast_err), + "failed to write extern lib types"); + fclose(fd); + return -1; + } - fclose(fp); + result = wr_extern_fns(fd, gen->extern_fns, gen->extern_fns_count); + if (!result) + { + snprintf(wrlast_err, sizeof(wrlast_err), + "failed to write extern lib functions"); + fclose(fd); + return -1; + } + + result = wr_ops(fd, gen->ops, gen->ops_count); + if (!result) + { + snprintf(wrlast_err, sizeof(wrlast_err), "failed to write opcodes"); + fclose(fd); + return -1; + } + + fclose(fd); return 0; } diff --git a/src/compiler/writer/wr_consts.c b/src/compiler/writer/wr_consts.c new file mode 100644 index 0000000..7de72a6 --- /dev/null +++ b/src/compiler/writer/wr_consts.c @@ -0,0 +1,25 @@ +#include +#include +#include + +// Write constants table +bool wr_consts(FILE *fd, fzl_const_hash_pool_t *consts) +{ + if (!fd || !consts) + return false; + + for (size_t i = 0; i < consts->size; i++) + { + fzl_const_t c = consts->array[i]; + fwrite(&c.type, sizeof(fzl_consttype_t), 1, fd); + + if (c.type == FZL_CONSTTYPE_STRING) + { + size_t strlen = c.as.string.length; + fwrite(&c.as.string.length, sizeof(uint16_t), 1, fd); + fwrite(c.as.string.chars, sizeof(char), strlen, fd); + } + } + + return true; +} diff --git a/src/compiler/writer/wr_extern_fns.c b/src/compiler/writer/wr_extern_fns.c new file mode 100644 index 0000000..ace030a --- /dev/null +++ b/src/compiler/writer/wr_extern_fns.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include + +// Write arguments +bool write_args(FILE *fd, fzl_extern_arg_t *args, size_t args_count) +{ + for (size_t i = 0; i < args_count; i++) + { + fzl_extern_arg_t *arg = &args[i]; + fwrite(&arg->is_out, sizeof(uint8_t), 1, fd); + fwrite(&arg->type.is_primitive, sizeof(uint8_t), 1, fd); + if (arg->type.is_primitive) + fwrite(&arg->type.primitive, sizeof(uint8_t), 1, fd); + else + fwrite(&arg->type.type_slot, sizeof(uint16_t), 1, fd); + } + + return true; +} + +// Write external function references +bool wr_extern_fns(FILE *fd, fzl_extern_fn_t *fns, size_t fns_count) +{ + if (!fd || !fns) + return false; + + for (size_t i = 0; i < fns_count; i++) + { + fzl_extern_fn_t *fn = &fns[i]; + + size_t used_name_sz = strlen(fn->used_name); + bool has_symbol_name = fn->symbol_name != NULL; + + fwrite(&used_name_sz, sizeof(uint16_t), 1, fd); + fwrite(fn->used_name, sizeof(char), used_name_sz, fd); + fwrite(&has_symbol_name, sizeof(uint8_t), 1, fd); + + if (has_symbol_name) + { + size_t symbol_name_sz = strlen(fn->symbol_name); + fwrite(&symbol_name_sz, sizeof(uint16_t), 1, fd); + fwrite(fn->symbol_name, sizeof(char), symbol_name_sz, fd); + } + + fwrite(&fn->has_return, sizeof(uint8_t), 1, fd); + if (fn->has_return) + { + fwrite(&fn->ret_type.is_primitive, sizeof(uint8_t), 1, fd); + if (fn->ret_type.is_primitive) + fwrite(&fn->ret_type.primitive, sizeof(uint8_t), 1, fd); + else + fwrite(&fn->ret_type.type_slot, sizeof(uint16_t), 1, fd); + } + + fwrite(&fn->args_count, sizeof(uint16_t), 1, fd); + if (fn->args_count > 0) + if (!write_args(fd, fn->args, fn->args_count)) + return false; + } + + return true; +} diff --git a/src/compiler/writer/wr_extern_libs.c b/src/compiler/writer/wr_extern_libs.c new file mode 100644 index 0000000..1b591d1 --- /dev/null +++ b/src/compiler/writer/wr_extern_libs.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include +#include + +// Writer external lib names +bool wr_extern_libs(FILE *fd, fzl_extern_lib_t *libs, size_t libs_count) +{ + if (!fd || !libs) + return false; + + for (size_t i = 0; i < libs_count; i++) + { + fzl_extern_lib_t *lib = &libs[i]; + + if (!lib || !lib->name) + return false; + + size_t len = strlen(lib->name); + if (len < 1) + return false; + + fwrite(&len, sizeof(size_t), 1, fd); + fwrite(lib->name, sizeof(char), len, fd); + } + + return true; +} diff --git a/src/compiler/writer/wr_extern_types.c b/src/compiler/writer/wr_extern_types.c new file mode 100644 index 0000000..9a615aa --- /dev/null +++ b/src/compiler/writer/wr_extern_types.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +// Write structure +bool write_struct(FILE *fd, fzl_extern_type_t *st) +{ + fwrite(&st->structure.fields_count, sizeof(uint16_t), 1, fd); + + for (size_t i = 0; i < st->structure.fields_count; i++) + { + fzl_extern_struct_field_t *field = &st->structure.fields[i]; + + bool has_name = field->name != NULL; + fwrite(&has_name, sizeof(uint8_t), 1, fd); + if (field->name) + { + size_t name_sz = strlen(field->name); + if (name_sz < 1) + return false; + + fwrite(&name_sz, sizeof(uint16_t), 1, fd); + fwrite(field->name, sizeof(char), name_sz, fd); + } + + fwrite(&field->type.is_primitive, sizeof(uint8_t), 1, fd); + if (field->type.is_primitive) + fwrite(&field->type.primitive, sizeof(uint8_t), 1, fd); + else + fwrite(&field->type.type_slot, sizeof(uint16_t), 1, fd); + } + + return true; +} + +// Write external libs type definitions +bool wr_extern_types(FILE *fd, fzl_extern_type_t *types, size_t types_count) +{ + if (!fd || !types) + return false; + + for (size_t i = 0; i < types_count; i++) + { + fzl_extern_type_t *type = &types[i]; + fwrite(&type->kind, sizeof(uint8_t), 1, fd); + + size_t name_sz = strlen(type->name); + fwrite(&name_sz, sizeof(uint16_t), 1, fd); + fwrite(type->name, sizeof(char), name_sz, fd); + + if (type->kind == FZL_EXTERN_KIND_STRUCT) + { + if (!write_struct(fd, type)) + return false; + } + else if (type->kind == FZL_EXTERN_KIND_REF || + type->kind == FZL_EXTERN_KIND_ALIAS) + { + fwrite(&type->ref_target.is_primitive, sizeof(uint8_t), 1, fd); + if (type->ref_target.is_primitive) + fwrite(&type->ref_target.primitive, sizeof(uint8_t), 1, fd); + else + fwrite(&type->ref_target.type_slot, sizeof(uint16_t), 1, fd); + } + } + + return true; +} diff --git a/src/compiler/writer/wr_ops.c b/src/compiler/writer/wr_ops.c new file mode 100644 index 0000000..59c692a --- /dev/null +++ b/src/compiler/writer/wr_ops.c @@ -0,0 +1,14 @@ +#include +#include + +// Write opcodes +bool wr_ops(FILE *fd, size_t *ops, size_t ops_count) +{ + if (!fd || !ops) + return false; + + if (ops_count > 0) + fwrite(ops, sizeof(uint64_t), ops_count, fd); + + return true; +}