From 5c96f9622033cc18d24000722ce4d84c76a569e2 Mon Sep 17 00:00:00 2001 From: samsonium Date: Fri, 30 Oct 2026 20:32:14 +0300 Subject: [PATCH] wip: working on dynamic linking - Feat: add analyzers for: - external functions - reference - structures - type definitions - Feat: add new nodes to debug print (ast) --- CMakeLists.txt | 4 ++ include/common/fzl_types.h | 2 + include/compiler/internals/analyzer.h | 5 ++ src/compiler/analyzer/an_common.c | 20 +++++++ src/compiler/analyzer/an_externfn.c | 75 +++++++++++++++++++++++++++ src/compiler/analyzer/an_ref.c | 39 ++++++++++++++ src/compiler/analyzer/an_struct.c | 52 +++++++++++++++++++ src/compiler/analyzer/an_typedef.c | 51 ++++++++++++++++++ src/compiler/fzl_debug.c | 46 ++++++++++++++++ 9 files changed, 294 insertions(+) create mode 100644 src/compiler/analyzer/an_externfn.c create mode 100644 src/compiler/analyzer/an_ref.c create mode 100644 src/compiler/analyzer/an_struct.c create mode 100644 src/compiler/analyzer/an_typedef.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d20174c..e0b5ddc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,12 +50,16 @@ if (NOT FZL_SKIP_C) src/compiler/analyzer/an_conditional.c src/compiler/analyzer/an_construct.c src/compiler/analyzer/an_declaration.c + src/compiler/analyzer/an_externfn.c src/compiler/analyzer/an_field.c src/compiler/analyzer/an_function.c src/compiler/analyzer/an_identifier.c src/compiler/analyzer/an_loop.c + src/compiler/analyzer/an_ref.c src/compiler/analyzer/an_return.c src/compiler/analyzer/an_strfmt.c + src/compiler/analyzer/an_struct.c + src/compiler/analyzer/an_typedef.c src/compiler/analyzer/an_unarycond.c src/compiler/analyzer/an_unarymath.c src/compiler/parser/pa_and.c diff --git a/include/common/fzl_types.h b/include/common/fzl_types.h index 65069ce..d82eb73 100644 --- a/include/common/fzl_types.h +++ b/include/common/fzl_types.h @@ -7,6 +7,8 @@ typedef enum FZL_TYPE_OBJECT, FZL_TYPE_EXTERN_FN, + FZL_TYPE_HANDLE, + FZL_TYPE_STRUCT, FZL_TYPE_STRING, FZL_TYPE_CHAR, diff --git a/include/compiler/internals/analyzer.h b/include/compiler/internals/analyzer.h index 095a205..d830ed7 100644 --- a/include/compiler/internals/analyzer.h +++ b/include/compiler/internals/analyzer.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -31,6 +32,10 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node); fzl_an_res_t analyze_unarycond(fzl_analyzer_t *analyzer, fzl_node_t *unary); fzl_an_res_t analyze_assign(fzl_analyzer_t *analyzer, fzl_node_t *assign_node); fzl_an_res_t analyze_strfmt(fzl_analyzer_t *analyzer, fzl_node_t *strfmt_node); +fzl_an_res_t analyze_typedef(fzl_analyzer_t *analyzer, fzl_node_t *td_node); +fzl_an_res_t analyze_struct(fzl_analyzer_t *analyzer, fzl_node_t *struct_node); +fzl_an_res_t analyze_ref(fzl_analyzer_t *analyzer, fzl_node_t *ref_node); +fzl_an_res_t analyze_externfn(fzl_analyzer_t *analyzer, fzl_node_t *externfn); fzl_an_ctx_t *an_nest_ctx(fzl_analyzer_t *analyzer, fzl_an_ctx_type_t type); fzl_an_ctx_t *an_fin_ctx(fzl_analyzer_t *analyzer); diff --git a/src/compiler/analyzer/an_common.c b/src/compiler/analyzer/an_common.c index a2baff9..e7955e1 100644 --- a/src/compiler/analyzer/an_common.c +++ b/src/compiler/analyzer/an_common.c @@ -15,6 +15,26 @@ fzl_an_res_t analyze_common(fzl_analyzer_t *analyzer, fzl_node_t *node) fzl_an_res_t res = {.error = false, .type = FZL_TYPE_NULL, .classname = NULL}; switch (node->type) { + case FZL_NODETYPE_REFERENCE: + res = analyze_ref(analyzer, node); + break; + + case FZL_NODETYPE_STRUCT: + res = analyze_struct(analyzer, node); + break; + + case FZL_NODETYPE_ALIAS: + res.type = an_toktotype(node->token); + break; + + case FZL_NODETYPE_HANDLE: + res.type = FZL_TYPE_HANDLE; + break; + + case FZL_NODETYPE_TYPEDEF: + res = analyze_typedef(analyzer, node); + break; + case FZL_NODETYPE_FMT_STRING: res = analyze_strfmt(analyzer, node); break; diff --git a/src/compiler/analyzer/an_externfn.c b/src/compiler/analyzer/an_externfn.c new file mode 100644 index 0000000..85648d6 --- /dev/null +++ b/src/compiler/analyzer/an_externfn.c @@ -0,0 +1,75 @@ +#include "common/fzl_types.h" +#include "compiler/fzl_parser.h" +#include "compiler/fzl_token.h" +#include "compiler/utils/fzl_symtable.h" +#include +#include +#include +#include +#include + +// Analyze external function definition +fzl_an_res_t analyze_externfn(fzl_analyzer_t *analyzer, fzl_node_t *externfn) +{ + if (!analyzer) + return (fzl_an_res_t){.error = true}; + + if (!externfn || externfn->type != FZL_NODETYPE_EXTERN_FN) + { + an_push_error(analyzer, NULL, "node is not an external function"); + return (fzl_an_res_t){.error = true}; + } + + for (size_t i = 0; i < externfn->ext_fn.args_count; i++) + { + fzl_an_res_t res = analyze_common(analyzer, externfn->ext_fn.args[i]); + if (res.error) + return (fzl_an_res_t){.error = true}; + } + + if (externfn->ext_fn.type->type == FZL_TOKTYPE_NAME) + { + fzl_sym_t sym; + bool found = false; + for (ssize_t i = analyzer->symbols_top - 1; i >= 0; i--) + { + if ((found = fzl_symt_get(analyzer->symbols[i], + (char *)externfn->ext_fn.type->value, &sym))) + break; + } + + if (!found) + { + snprintf(an_problem, sizeof(an_problem), + "cannot find '%s' used as return type", + (char *)externfn->ext_fn.type->value); + an_push_error(analyzer, externfn->ext_fn.type, an_problem); + return (fzl_an_res_t){.error = true}; + } + } + + fzl_symtable_res_t wrres = + fzl_symt_put(analyzer->symbols[0], externfn, + (char *)externfn->ext_fn.name, FZL_TYPE_EXTERN_FN, 0); + if (wrres != FZL_SYMTABLE_RESULT_OK) + { + if (wrres == FZL_SYMTABLE_RESULT_EXISTS) + { + snprintf(an_problem, sizeof(an_problem), + "symbol '%s' already has been declared", externfn->ext_fn.name); + an_push_error(analyzer, externfn->token, an_problem); + return (fzl_an_res_t){.error = true}; + } + else + { + snprintf(an_problem, sizeof(an_problem), "cannot store symbol '%s'", + externfn->ext_fn.name); + } + + an_push_error(analyzer, externfn->token, an_problem); + return (fzl_an_res_t){.error = true}; + } + + return (fzl_an_res_t){ + .error = false, .type = FZL_TYPE_EXTERN_FN, .classname = NULL}; +} diff --git a/src/compiler/analyzer/an_ref.c b/src/compiler/analyzer/an_ref.c new file mode 100644 index 0000000..fc40bbc --- /dev/null +++ b/src/compiler/analyzer/an_ref.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include + +// Analyze reference +fzl_an_res_t analyze_ref(fzl_analyzer_t *analyzer, fzl_node_t *ref_node) +{ + if (!analyzer) + return (fzl_an_res_t){.error = true}; + + if (!ref_node || ref_node->type != FZL_NODETYPE_STRUCT) + { + an_push_error(analyzer, NULL, "node is not a structure"); + return (fzl_an_res_t){.error = true}; + } + + char *refto = (char *)ref_node->token->value; + fzl_sym_t sym; + bool found = false; + for (ssize_t i = analyzer->symbols_top - 1; i >= 0; i--) + { + if ((found = fzl_symt_get(analyzer->symbols[i], refto, &sym))) + break; + } + + if (!found) + { + snprintf(an_problem, sizeof(an_problem), "cannot find name '%s'", refto); + an_push_error(analyzer, ref_node->token, an_problem); + return (fzl_an_res_t){.error = true}; + } + + return (fzl_an_res_t){ + .error = false, .type = FZL_TYPE_HANDLE, .classname = refto}; +} diff --git a/src/compiler/analyzer/an_struct.c b/src/compiler/analyzer/an_struct.c new file mode 100644 index 0000000..6eb5e67 --- /dev/null +++ b/src/compiler/analyzer/an_struct.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +// Analyze structure definition +fzl_an_res_t analyze_struct(fzl_analyzer_t *analyzer, fzl_node_t *struct_node) +{ + if (!analyzer) + return (fzl_an_res_t){.error = true}; + + if (!struct_node || struct_node->type != FZL_NODETYPE_STRUCT) + { + an_push_error(analyzer, NULL, "node is not a structure"); + return (fzl_an_res_t){.error = true}; + } + + if (struct_node->structure.entries_count < 1) + { + an_push_warning(analyzer, struct_node->token, "empty structure"); + return (fzl_an_res_t){.error = false}; + } + + for (size_t i = 0; i < struct_node->structure.entries_count; i++) + { + fzl_node_t *entry = struct_node->structure.entries[i]; + if (entry->type != FZL_NODETYPE_DECLARATION && + entry->type != FZL_NODETYPE_IDENTIFIER) + { + an_push_error( + analyzer, entry->token, + "structure can contain only declarations and another structures"); + return (fzl_an_res_t){.error = true}; + } + + fzl_an_res_t res = analyze_common(analyzer, entry); + if (res.error) + return (fzl_an_res_t){.error = true}; + + if (res.type == FZL_TYPE_OBJECT) + { + an_push_error(analyzer, entry->token, + "cannot store object inside struct"); + return (fzl_an_res_t){.error = true}; + } + } + + return (fzl_an_res_t){ + .error = false, .type = FZL_TYPE_STRUCT, .classname = NULL}; +} diff --git a/src/compiler/analyzer/an_typedef.c b/src/compiler/analyzer/an_typedef.c new file mode 100644 index 0000000..2dc074e --- /dev/null +++ b/src/compiler/analyzer/an_typedef.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +// Analyze type definition +fzl_an_res_t analyze_typedef(fzl_analyzer_t *analyzer, fzl_node_t *td_node) +{ + if (!analyzer) + return (fzl_an_res_t){.error = true}; + + if (!td_node || td_node->type != FZL_NODETYPE_TYPEDEF) + { + an_push_error(analyzer, NULL, "node is not a type definition"); + return (fzl_an_res_t){.error = true}; + } + + fzl_an_res_t res = analyze_common(analyzer, td_node->typedefinition.type); + if (res.error) + return (fzl_an_res_t){.error = true}; + + fzl_nodetype_t type = td_node->typedefinition.type->type; + if (type != FZL_NODETYPE_ALIAS && type != FZL_NODETYPE_STRUCT && + type != FZL_NODETYPE_HANDLE) + { + an_push_error(analyzer, td_node->token, + "only alias, structure and handle are allowed in type " + "definition value"); + return (fzl_an_res_t){.error = true}; + } + + fzl_symtable_res_t putres = + fzl_symt_put(analyzer->symbols[0], td_node, + td_node->typedefinition.typename, res.type, 0); + if (putres != FZL_SYMTABLE_RESULT_OK) + { + if (putres == FZL_SYMTABLE_RESULT_EXISTS) + snprintf(an_problem, sizeof(an_problem), + "symbol '%s' already has been declared", + td_node->typedefinition.typename); + else + snprintf(an_problem, sizeof(an_problem), "cannot store symbol '%s'", + td_node->typedefinition.typename); + + an_push_error(analyzer, td_node->token, an_problem); + return (fzl_an_res_t){.error = true}; + } + + return (fzl_an_res_t){.error = false, .type = res.type, .classname = NULL}; +} diff --git a/src/compiler/fzl_debug.c b/src/compiler/fzl_debug.c index 536fa89..604b8b6 100644 --- a/src/compiler/fzl_debug.c +++ b/src/compiler/fzl_debug.c @@ -32,6 +32,52 @@ void print_node(fzl_node_t *node, int level) switch (node->type) { + case FZL_NODETYPE_EXTERN: + printf("%s Extern bindings to library '%s':\n", levelbuf, + node->ext.libname); + printf("-%s Types:\n", levelbuf); + for (size_t i = 0; i < node->ext.typedefs_count; i++) + print_node(node->ext.typedefs[i], level + 2); + printf("-%s Functions:\n", levelbuf); + for (size_t i = 0; i < node->ext.fns_count; i++) + print_node(node->ext.fns[i], level + 2); + break; + + case FZL_NODETYPE_EXTERN_FN: + printf("%s External function '%s' (original name %s), rettype '%s':\n", + levelbuf, node->ext_fn.name, node->ext_fn.original_name, + (char *)node->ext_fn.type->value); + printf("-%s Arguments:\n", levelbuf); + for (size_t i = 0; i < node->ext_fn.args_count; i++) + print_node(node->ext_fn.args[i], level + 2); + break; + + case FZL_NODETYPE_REFERENCE: + printf("%s Reference (pointer type) to '%s'\n", levelbuf, + (char *)node->token->value); + break; + + case FZL_NODETYPE_STRUCT: + printf("%s Structure '%s' (original name %s):\n", levelbuf, + (char *)node->token->value, node->structure.original_name); + for (size_t i = 0; i < node->structure.entries_count; i++) + print_node(node->structure.entries[i], level + 1); + break; + + case FZL_NODETYPE_ALIAS: + printf("%s Type alias to '%s'\n", levelbuf, (char *)node->token->value); + break; + + case FZL_NODETYPE_HANDLE: + printf("%s Opaque pointer (handle)\n", levelbuf); + break; + + case FZL_NODETYPE_TYPEDEF: + printf("%s Type definition '%s':\n", levelbuf, + node->typedefinition.typename); + print_node(node->typedefinition.type, level + 1); + break; + case FZL_NODETYPE_UNARY_MINUS: printf("%s Unary '-':\n", levelbuf); print_node(node->unary_op.operand, level + 1);