From c61322718d1eacf7b92d70ab752a36ccf3512ffa Mon Sep 17 00:00:00 2001 From: samsonium Date: Tue, 27 Oct 2026 14:12:09 +0300 Subject: [PATCH] fix: some analysis stage problems --- include/compiler/fzl_analyzer.h | 2 ++ src/compiler/analyzer/an_call.c | 15 ++++++++------- src/compiler/analyzer/an_conditional.c | 10 ++++++++-- src/compiler/analyzer/an_field.c | 4 ++-- src/compiler/analyzer/an_function.c | 8 ++++---- src/compiler/analyzer/context.c | 4 +++- src/compiler/fzl_analyzer.c | 4 ++-- ...alyzer_continues_after_if_without_else.fzs | 9 +++++++++ tests/programs/pos_function_external_call.fzs | 12 ++++++++++++ tests/programs/pos_method_call_via_field.fzs | 19 +++++++++++++++++++ 10 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 tests/programs/neg_analyzer_continues_after_if_without_else.fzs create mode 100644 tests/programs/pos_function_external_call.fzs create mode 100644 tests/programs/pos_method_call_via_field.fzs diff --git a/include/compiler/fzl_analyzer.h b/include/compiler/fzl_analyzer.h index 76cced5..37a1659 100644 --- a/include/compiler/fzl_analyzer.h +++ b/include/compiler/fzl_analyzer.h @@ -32,6 +32,8 @@ typedef struct fzl_an_ctx struct fzl_an_ctx *parent; fzl_an_ctx_type_t type; + fzl_symtable_t *symbols; + size_t symbols_level; union { diff --git a/src/compiler/analyzer/an_call.c b/src/compiler/analyzer/an_call.c index 96d1bf9..4c4fb0c 100644 --- a/src/compiler/analyzer/an_call.c +++ b/src/compiler/analyzer/an_call.c @@ -106,9 +106,9 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) .error = false, .type = FZL_TYPE_NULL, .classname = NULL}; } - fzl_an_res_t callee_res = analyze_common(analyzer, callee); - if (callee_res.error) - return (fzl_an_res_t){.error = true}; + // fzl_an_res_t callee_res = analyze_common(analyzer, callee); + // if (callee_res.error) + // return (fzl_an_res_t){.error = true}; fzl_sym_t sym; bool sym_found = false; @@ -148,11 +148,12 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) return (fzl_an_res_t){.error = true}; } - if (sym.node->fn.args_count != call_node->call.args_count) + size_t start_i = is_method ? 1 : 0; + if ((sym.node->fn.args_count - start_i) != call_node->call.args_count) { snprintf(call_problem, sizeof(call_problem), "expected %zu argument(s) while %zu is specified", - sym.node->fn.args_count, call_node->call.args_count); + sym.node->fn.args_count, call_node->call.args_count - start_i); an_push_error(analyzer, call_node->token, call_problem); if (tmp_method_name != NULL) @@ -164,7 +165,6 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) return (fzl_an_res_t){.error = true}; } - size_t start_i = is_method ? 1 : 0; for (size_t i = start_i; i < sym.node->fn.args_count; i++) { fzl_node_t *arg = sym.node->fn.args[i]; @@ -173,7 +173,8 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) if (req_type == FZL_TYPE_OBJECT) req_classname = arg->var.type->value; - fzl_an_res_t got = analyze_common(analyzer, call_node->call.args[i]); + fzl_an_res_t got = + analyze_common(analyzer, call_node->call.args[i - start_i]); if (got.error) { if (tmp_method_name != NULL) diff --git a/src/compiler/analyzer/an_conditional.c b/src/compiler/analyzer/an_conditional.c index f37dd48..1e5ec96 100644 --- a/src/compiler/analyzer/an_conditional.c +++ b/src/compiler/analyzer/an_conditional.c @@ -20,9 +20,15 @@ fzl_an_res_t analyze_conditional(fzl_analyzer_t *analyzer, fzl_node_t *cond) fzl_an_res_t cond_res = analyze_common(analyzer, cond->cond.condition); fzl_an_res_t true_res = analyze_common(analyzer, cond->cond.true_block); - fzl_an_res_t else_res = analyze_common(analyzer, cond->cond.else_block); - if (cond_res.error || true_res.error || else_res.error) + if (cond->cond.else_block) + { + fzl_an_res_t else_res = analyze_common(analyzer, cond->cond.else_block); + if (else_res.error) + return (fzl_an_res_t){.error = true}; + } + + if (cond_res.error || true_res.error) return (fzl_an_res_t){.error = true}; if (cond_res.type != FZL_TYPE_BOOL) diff --git a/src/compiler/analyzer/an_field.c b/src/compiler/analyzer/an_field.c index 15e728d..29fea9c 100644 --- a/src/compiler/analyzer/an_field.c +++ b/src/compiler/analyzer/an_field.c @@ -15,7 +15,7 @@ extern fzl_type_t an_toktotype(fzl_token_t *tok); // Analyze field access fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) { - if (analyzer) + if (!analyzer) return (fzl_an_res_t){.error = true}; if (!field || field->type != FZL_NODETYPE_FIELD) @@ -46,7 +46,7 @@ fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) break; } - if (sym_found) + if (!sym_found) { snprintf(field_problem, sizeof(field_problem), "class '%s' not found", parent.classname); diff --git a/src/compiler/analyzer/an_function.c b/src/compiler/analyzer/an_function.c index ee6bcc4..e2f619c 100644 --- a/src/compiler/analyzer/an_function.c +++ b/src/compiler/analyzer/an_function.c @@ -81,7 +81,7 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) analyzer->alloc_names[analyzer->alloc_names_top++] = methodname; fzl_symtable_res_t putres = - fzl_symt_put(analyzer->symbols[analyzer->symbols_top - 2], fn_node, + fzl_symt_put(analyzer->symbols[ctx->symbols_level - 1], fn_node, methodname, rettype, 0); if (putres != FZL_SYMTABLE_RESULT_OK) { @@ -99,13 +99,13 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) an_fin_ctx(analyzer); return (fzl_an_res_t){.error = true}; } - fzl_symt_setobjclass(analyzer->symbols[analyzer->symbols_top - 1], - methodname, classname); + fzl_symt_setobjclass(analyzer->symbols[ctx->symbols_level - 1], methodname, + classname); } else { fzl_symtable_res_t putres = - fzl_symt_put(analyzer->symbols[analyzer->symbols_top - 1], fn_node, + fzl_symt_put(analyzer->symbols[analyzer->symbols_top - 2], fn_node, (char *)fn_node->fn.name->value, rettype, 0); if (putres != FZL_SYMTABLE_RESULT_OK) { diff --git a/src/compiler/analyzer/context.c b/src/compiler/analyzer/context.c index e2242e0..2c3a361 100644 --- a/src/compiler/analyzer/context.c +++ b/src/compiler/analyzer/context.c @@ -21,8 +21,10 @@ fzl_an_ctx_t *an_nest_ctx(fzl_analyzer_t *analyzer, fzl_an_ctx_type_t type) else ctx->parent = NULL; + ctx->symbols = fzl_mksymt(); + ctx->symbols_level = analyzer->symbols_top; analyzer->ctx = ctx; - analyzer->symbols[analyzer->symbols_top++] = fzl_mksymt(); + analyzer->symbols[analyzer->symbols_top++] = ctx->symbols; return ctx; } diff --git a/src/compiler/fzl_analyzer.c b/src/compiler/fzl_analyzer.c index e2a1d43..b35d0cc 100644 --- a/src/compiler/fzl_analyzer.c +++ b/src/compiler/fzl_analyzer.c @@ -47,7 +47,7 @@ bool an_push_error(fzl_analyzer_t *analyzer, fzl_token_t *tok, char *error) size_t ei = aerrors_top++; if (tok != NULL) - snprintf(aerrors[ei], sizeof(aerrors[ei]), "'%s'(%zu:%zu) => %s", + snprintf(aerrors[ei], sizeof(aerrors[ei]), "'%s':%zu:%zu => %s", tok->filename, tok->ln, tok->cn, error); else snprintf(aerrors[ei], sizeof(aerrors[ei]), " => %s", @@ -64,7 +64,7 @@ bool an_push_warning(fzl_analyzer_t *analyzer, fzl_token_t *tok, char *warning) size_t wi = awarnings_top++; if (tok != NULL) - snprintf(awarnings[wi], sizeof(awarnings[wi]), "'%s'(%zu:%zu) => %s", + snprintf(awarnings[wi], sizeof(awarnings[wi]), "'%s':%zu:%zu => %s", tok->filename, tok->ln, tok->cn, warning); else snprintf(awarnings[wi], sizeof(awarnings[wi]), " => %s", diff --git a/tests/programs/neg_analyzer_continues_after_if_without_else.fzs b/tests/programs/neg_analyzer_continues_after_if_without_else.fzs new file mode 100644 index 0000000..f43f3e6 --- /dev/null +++ b/tests/programs/neg_analyzer_continues_after_if_without_else.fzs @@ -0,0 +1,9 @@ +fn choose(bool flag) int +{ + if (flag) + return 1; + return 0; +} + +int invalid = "not an integer"; +exit(1); diff --git a/tests/programs/pos_function_external_call.fzs b/tests/programs/pos_function_external_call.fzs new file mode 100644 index 0000000..d5d76ad --- /dev/null +++ b/tests/programs/pos_function_external_call.fzs @@ -0,0 +1,12 @@ +fn doSomeWork() +{ + printline("Some work"); +} + +fn sum(int a, int b) int +{ + return a + b; +} + +int result = sum(5, 6); +printline(result); diff --git a/tests/programs/pos_method_call_via_field.fzs b/tests/programs/pos_method_call_via_field.fzs new file mode 100644 index 0000000..c2f057c --- /dev/null +++ b/tests/programs/pos_method_call_via_field.fzs @@ -0,0 +1,19 @@ +class Node +{ + Node next; + + fn ping() + { + printline("ping"); + } + + fn pingNext() + { + this.next.ping(); + } +} + +Node head = new Node; +Node tail = new Node; +head.next = tail; +head.pingNext();