From dc80de66e4f606636b94b3a55c94866fad141726 Mon Sep 17 00:00:00 2001 From: samsonium Date: Tue, 27 Oct 2026 15:40:25 +0300 Subject: [PATCH] fix: review problems --- include/compiler/fzl_analyzer.h | 6 ++ src/compiler/analyzer/an_assign.c | 20 +++--- src/compiler/analyzer/an_binmath.c | 18 +++--- src/compiler/analyzer/an_block.c | 27 ++++---- src/compiler/analyzer/an_break.c | 4 +- src/compiler/analyzer/an_call.c | 88 ++++++++++++++++---------- src/compiler/analyzer/an_class.c | 12 ++-- src/compiler/analyzer/an_condition.c | 22 ++----- src/compiler/analyzer/an_conditional.c | 8 +-- src/compiler/analyzer/an_construct.c | 8 +-- src/compiler/analyzer/an_declaration.c | 19 ++---- src/compiler/analyzer/an_field.c | 23 +++---- src/compiler/analyzer/an_function.c | 17 ++--- src/compiler/analyzer/an_identifier.c | 8 +-- src/compiler/analyzer/an_loop.c | 25 +++----- src/compiler/analyzer/an_return.c | 60 +++++++++++++----- src/compiler/analyzer/an_unarycond.c | 2 +- src/compiler/analyzer/an_unarymath.c | 2 +- src/compiler/fzl_analyzer.c | 2 + src/compiler/utils/fzl_linked.c | 2 +- src/vm/fzl_vm.c | 3 +- 21 files changed, 197 insertions(+), 179 deletions(-) diff --git a/include/compiler/fzl_analyzer.h b/include/compiler/fzl_analyzer.h index 37a1659..4050ba4 100644 --- a/include/compiler/fzl_analyzer.h +++ b/include/compiler/fzl_analyzer.h @@ -76,6 +76,12 @@ void fzl_analyze(fzl_analyzer_t *analyzer); // Free analyzer void fzl_freeanalyzer(fzl_analyzer_t *analyzer); +extern char an_problem[256]; + +bool an_is_compatible(fzl_type_t a, fzl_type_t b, char *ac, char *bc); +char *an_typetostr(fzl_type_t type, char *classname); +fzl_type_t an_toktotype(fzl_token_t *tok); + fzl_an_res_t analyze_common(fzl_analyzer_t *analyzer, fzl_node_t *node); fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node); fzl_an_res_t analyze_identifier(fzl_analyzer_t *analyzer, fzl_node_t *id); diff --git a/src/compiler/analyzer/an_assign.c b/src/compiler/analyzer/an_assign.c index a4109d7..120a6cd 100644 --- a/src/compiler/analyzer/an_assign.c +++ b/src/compiler/analyzer/an_assign.c @@ -3,12 +3,6 @@ #include #include -char asn_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern bool an_is_compatible(fzl_type_t a, fzl_type_t b, char *ac, char *bc); -extern char *an_typetostr(fzl_type_t type, char *classname); - // Analyze assigns fzl_an_res_t analyze_assign(fzl_analyzer_t *analyzer, fzl_node_t *assign_node) { @@ -17,7 +11,7 @@ fzl_an_res_t analyze_assign(fzl_analyzer_t *analyzer, fzl_node_t *assign_node) if (!assign_node || assign_node->type != FZL_NODETYPE_ASSIGN) { - an_push_error(analyzer, NULL, "node is not typeof ASSIGN"); + an_push_error(analyzer, NULL, "node is not assignment"); return (fzl_an_res_t){.error = true}; } @@ -35,17 +29,19 @@ fzl_an_res_t analyze_assign(fzl_analyzer_t *analyzer, fzl_node_t *assign_node) left->type != FZL_NODETYPE_IDENTIFIER && left->type != FZL_NODETYPE_FIELD) { an_push_error(analyzer, left->token, - "this type of assignment left is not supported"); + "left side must be one of these: declaration, identifier or " + "field access"); return (fzl_an_res_t){.error = true}; } if (!an_is_compatible(leftside.type, rightside.type, leftside.classname, rightside.classname)) { - snprintf(asn_problem, sizeof(asn_problem), "cannot assign %s to %s", - an_typetostr(rightside.type, rightside.classname), - an_typetostr(leftside.type, leftside.classname)); - an_push_error(analyzer, assign_node->binary_op.right->token, asn_problem); + snprintf(an_problem, sizeof(an_problem), + "incompatible types - '%s' is expected, got '%s'", + an_typetostr(leftside.type, leftside.classname), + an_typetostr(rightside.type, rightside.classname)); + an_push_error(analyzer, assign_node->binary_op.right->token, an_problem); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_binmath.c b/src/compiler/analyzer/an_binmath.c index 2e89aac..2d2f522 100644 --- a/src/compiler/analyzer/an_binmath.c +++ b/src/compiler/analyzer/an_binmath.c @@ -1,9 +1,7 @@ #include #include #include - -// defined in `compiler/analyzer/utility.c` -extern bool an_is_compatible(fzl_type_t a, fzl_type_t b, char *ac, char *bc); +#include // Analyze binary arithmetics fzl_an_res_t analyze_binmath(fzl_analyzer_t *analyzer, fzl_node_t *bin_node) @@ -18,7 +16,7 @@ fzl_an_res_t analyze_binmath(fzl_analyzer_t *analyzer, fzl_node_t *bin_node) bin_node->type != FZL_NODETYPE_POW && bin_node->type != FZL_NODETYPE_MOD)) { - an_push_error(analyzer, NULL, "node is not typeof binary math"); + an_push_error(analyzer, NULL, "node is not binary math operator"); return (fzl_an_res_t){.error = true}; } @@ -32,15 +30,19 @@ fzl_an_res_t analyze_binmath(fzl_analyzer_t *analyzer, fzl_node_t *bin_node) if (left.type < FZL_TYPE_INT8) { - an_push_error(analyzer, bin_node->binary_op.left->token, - "left side is not an integer type"); + snprintf(an_problem, sizeof(an_problem), + "integer type is expected, got '%s'", + an_typetostr(left.type, left.classname)); + an_push_error(analyzer, bin_node->binary_op.left->token, an_problem); return (fzl_an_res_t){.error = true}; } if (right.type < FZL_TYPE_INT8) { - an_push_error(analyzer, bin_node->binary_op.right->token, - "right side is not an integer type"); + snprintf(an_problem, sizeof(an_problem), + "integer type is expected, got '%s'", + an_typetostr(right.type, right.classname)); + an_push_error(analyzer, bin_node->binary_op.right->token, an_problem); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_block.c b/src/compiler/analyzer/an_block.c index 639dbe0..f4ce9be 100644 --- a/src/compiler/analyzer/an_block.c +++ b/src/compiler/analyzer/an_block.c @@ -5,12 +5,6 @@ #include #include -char block_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern fzl_type_t an_toktotype(fzl_token_t *tok); -extern char *an_typetostr(fzl_type_t type, char *classname); - // Analyze block fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node) { @@ -19,8 +13,8 @@ fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node) if (!block_node || block_node->type != FZL_NODETYPE_BLOCK) { - snprintf(block_problem, sizeof(block_problem), "node is not typeof BLOCK"); - an_push_error(analyzer, NULL, block_problem); + snprintf(an_problem, sizeof(an_problem), "node is not a block"); + an_push_error(analyzer, NULL, an_problem); return (fzl_an_res_t){.error = true}; } @@ -32,7 +26,7 @@ fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node) { if (has_return) an_push_warning(analyzer, block_node->list.entries[i]->token, - "this node will never execute"); + "this statement will never execute"); fzl_an_res_t entry_res = analyze_common(analyzer, block_node->list.entries[i]); @@ -65,10 +59,11 @@ fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node) { if (!has_return || block_node->list.entry_count < 1) { - snprintf(block_problem, sizeof(block_problem), - "expected 'return <%s>' in function because return type is %s", - rettype_str, rettype_str); - an_push_error(analyzer, block_node->token, block_problem); + snprintf(an_problem, sizeof(an_problem), + "'return <%s>' is expected in the function with non-null " + "return type", + rettype_str); + an_push_error(analyzer, block_node->token, an_problem); return (fzl_an_res_t){.error = true}; } @@ -76,10 +71,12 @@ fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node) block_node->list.entries[block_node->list.entry_count - 1]; if (last_node->type != FZL_NODETYPE_RETURN) { - snprintf(block_problem, sizeof(block_problem), + // NOTE: replace with ghost walker to check if all branch return an + // expected value type + snprintf(an_problem, sizeof(an_problem), "expected last statement in block to be 'return <%s>'", rettype_str); - an_push_error(analyzer, last_node->token, block_problem); + an_push_error(analyzer, last_node->token, an_problem); return (fzl_an_res_t){.error = true}; } } diff --git a/src/compiler/analyzer/an_break.c b/src/compiler/analyzer/an_break.c index b9a1f6d..fb83f44 100644 --- a/src/compiler/analyzer/an_break.c +++ b/src/compiler/analyzer/an_break.c @@ -10,7 +10,7 @@ fzl_an_res_t analyze_break(fzl_analyzer_t *analyzer, fzl_node_t *break_node) if (!break_node || break_node->type != FZL_NODETYPE_BREAK) { - an_push_error(analyzer, NULL, "node is not typeof BREAK"); + an_push_error(analyzer, NULL, "node is not a break statement"); return (fzl_an_res_t){.error = true}; } @@ -26,7 +26,7 @@ fzl_an_res_t analyze_break(fzl_analyzer_t *analyzer, fzl_node_t *break_node) if (!ctx || ctx->type != FZL_AN_CTX_TYPE_LOOP) { an_push_error(analyzer, break_node->token, - "cannot use 'break' outside loop"); + "cannot use 'break' outside the loop"); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_call.c b/src/compiler/analyzer/an_call.c index 4c4fb0c..3776b8d 100644 --- a/src/compiler/analyzer/an_call.c +++ b/src/compiler/analyzer/an_call.c @@ -9,8 +9,9 @@ #include #include -char *tmp_method_name = NULL; -char call_problem[256] = {0}; +char *tmp_method_name = NULL; +char *tmp_fnname = NULL; +char *tmp_classname = NULL; // Try to get symbol name from callee char *resolve_callee(fzl_analyzer_t *analyzer, fzl_node_t *callee, bool *method) @@ -21,7 +22,10 @@ char *resolve_callee(fzl_analyzer_t *analyzer, fzl_node_t *callee, bool *method) return (char *)callee->token->value; if (callee->type != FZL_NODETYPE_FIELD) + { + an_push_error(analyzer, callee->token, "unknown call format"); return NULL; + } *method = true; fzl_an_res_t parent_res = analyze_common(analyzer, callee->memb.parent); @@ -29,13 +33,14 @@ char *resolve_callee(fzl_analyzer_t *analyzer, fzl_node_t *callee, bool *method) return NULL; char *fn_name = callee->memb.field->token->value; + tmp_fnname = fn_name; + tmp_classname = parent_res.classname; size_t classname_len = strlen(parent_res.classname); size_t methodname_len = strlen(fn_name); tmp_method_name = malloc(classname_len + methodname_len + 2); if (!tmp_method_name) { - an_push_error(analyzer, callee->token, - "failed to allocate space for method name"); + an_push_error(analyzer, callee->token, "out of memory"); return NULL; } @@ -47,17 +52,12 @@ char *resolve_callee(fzl_analyzer_t *analyzer, fzl_node_t *callee, bool *method) return tmp_method_name; } -// defined in `compiler/analyzer/utility.c` -extern bool an_is_compatible(fzl_type_t a, fzl_type_t b, char *ac, char *bc); -extern char *an_typetostr(fzl_type_t type, char *classname); -extern fzl_type_t an_toktotype(fzl_token_t *tok); - // Analyze call node fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) { if (!call_node || call_node->type != FZL_NODETYPE_CALL) { - an_push_error(analyzer, NULL, "provided node is not typeof CALL"); + an_push_error(analyzer, NULL, "node is not call"); return (fzl_an_res_t){.error = true}; } @@ -78,14 +78,15 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) return (fzl_an_res_t){.error = true}; } + // NOTE: move into `compiler/analyzer/builtins.c` if (strcmp(callee_name, "printline") == 0 || strcmp(callee_name, "exit") == 0) { if (call_node->call.args_count != 1) { - snprintf(call_problem, sizeof(call_problem), + snprintf(an_problem, sizeof(an_problem), "'%s' builtin should be called with 1 argument instead of %zu", callee_name, call_node->call.args_count); - an_push_error(analyzer, call_node->token, call_problem); + an_push_error(analyzer, call_node->token, an_problem); if (tmp_method_name != NULL) { @@ -106,10 +107,6 @@ 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_sym_t sym; bool sym_found = false; for (ssize_t i = analyzer->symbols_top - 1; i >= 0; i--) @@ -120,9 +117,9 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) if (!sym_found) { - snprintf(call_problem, sizeof(call_problem), "cannot resolve symbol '%s'", + snprintf(an_problem, sizeof(an_problem), "cannot resolve symbol '%s'", callee_name); - an_push_error(analyzer, call_node->token, call_problem); + an_push_error(analyzer, call_node->token, an_problem); if (tmp_method_name != NULL) { @@ -135,9 +132,9 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) if (sym.node->type != FZL_NODETYPE_FUNCTION) { - snprintf(call_problem, sizeof(call_problem), "'%s' is not callable", + snprintf(an_problem, sizeof(an_problem), "'%s' is not callable", callee_name); - an_push_error(analyzer, call_node->token, call_problem); + an_push_error(analyzer, call_node->token, an_problem); if (tmp_method_name != NULL) { @@ -148,13 +145,24 @@ 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; - if ((sym.node->fn.args_count - start_i) != call_node->call.args_count) + size_t offset = is_method ? 1 : 0; + if ((sym.node->fn.args_count - offset) != 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 - start_i); - an_push_error(analyzer, call_node->token, call_problem); + if (is_method) + { + snprintf(an_problem, sizeof(an_problem), + "method '%s.%s' is expecting %zu argument(s), got %zu", + tmp_classname, tmp_fnname, sym.node->fn.args_count, + call_node->call.args_count - offset); + } + else + { + snprintf(an_problem, sizeof(an_problem), + "function '%s' is expecting %zu argument(s), got %zu", + callee_name, sym.node->fn.args_count, + call_node->call.args_count - offset); + } + an_push_error(analyzer, call_node->token, an_problem); if (tmp_method_name != NULL) { @@ -165,7 +173,7 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) return (fzl_an_res_t){.error = true}; } - for (size_t i = start_i; i < sym.node->fn.args_count; i++) + for (size_t i = offset; i < sym.node->fn.args_count; i++) { fzl_node_t *arg = sym.node->fn.args[i]; fzl_type_t req_type = an_toktotype(arg->var.type); @@ -174,7 +182,7 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) req_classname = arg->var.type->value; fzl_an_res_t got = - analyze_common(analyzer, call_node->call.args[i - start_i]); + analyze_common(analyzer, call_node->call.args[i - offset]); if (got.error) { if (tmp_method_name != NULL) @@ -187,11 +195,25 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node) if (!an_is_compatible(req_type, got.type, req_classname, got.classname)) { - snprintf(call_problem, sizeof(call_problem), - "expect argument %zu to be %s, got '%s'", i + 1, - an_typetostr(req_type, req_classname), - an_typetostr(got.type, got.classname)); - an_push_error(analyzer, call_node->token, call_problem); + if (is_method) + { + snprintf(an_problem, sizeof(an_problem), + "method '%s.%s' is expecting %zu argument to have type '%s', " + "got '%s'", + tmp_classname, tmp_fnname, i + 1 - offset, + an_typetostr(req_type, req_classname), + an_typetostr(got.type, got.classname)); + } + else + { + snprintf(an_problem, sizeof(an_problem), + "function '%s' is expecting %zu argument to have type '%s', " + "got '%s'", + callee_name, i + 1 - offset, + an_typetostr(req_type, req_classname), + an_typetostr(got.type, got.classname)); + } + an_push_error(analyzer, call_node->token, an_problem); if (tmp_method_name != NULL) { diff --git a/src/compiler/analyzer/an_class.c b/src/compiler/analyzer/an_class.c index da264b6..ceccd86 100644 --- a/src/compiler/analyzer/an_class.c +++ b/src/compiler/analyzer/an_class.c @@ -4,8 +4,6 @@ #include #include -char class_problem[256]; - // Analyze class declaration fzl_an_res_t analyze_class(fzl_analyzer_t *analyzer, fzl_node_t *class_node) { @@ -14,7 +12,7 @@ fzl_an_res_t analyze_class(fzl_analyzer_t *analyzer, fzl_node_t *class_node) if (!class_node || class_node->type != FZL_NODETYPE_CLASS) { - an_push_error(analyzer, NULL, "node is not typeof CLASS"); + an_push_error(analyzer, NULL, "node is not class"); return (fzl_an_res_t){.error = true}; } @@ -38,15 +36,15 @@ fzl_an_res_t analyze_class(fzl_analyzer_t *analyzer, fzl_node_t *class_node) { if (res == FZL_SYMTABLE_RESULT_EXISTS) { - snprintf(class_problem, sizeof(class_problem), + snprintf(an_problem, sizeof(an_problem), "name '%s' already has been declared", classname); - an_push_error(analyzer, class_node->token, class_problem); + an_push_error(analyzer, class_node->token, an_problem); } else { - snprintf(class_problem, sizeof(class_problem), "cannot store name '%s'", + snprintf(an_problem, sizeof(an_problem), "cannot store name '%s'", classname); - an_push_error(analyzer, class_node->token, class_problem); + an_push_error(analyzer, class_node->token, an_problem); } an_fin_ctx(analyzer); diff --git a/src/compiler/analyzer/an_condition.c b/src/compiler/analyzer/an_condition.c index 0a0505b..8473b54 100644 --- a/src/compiler/analyzer/an_condition.c +++ b/src/compiler/analyzer/an_condition.c @@ -3,12 +3,6 @@ #include #include -char bincond_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern bool an_is_compatible(fzl_type_t a, fzl_type_t b, char *ac, char *bc); -extern char *an_typetostr(fzl_type_t type, char *classname); - // Analyze binary conditional nodes fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node) { @@ -24,7 +18,7 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node) cond_node->type != FZL_NODETYPE_EQUAL && cond_node->type != FZL_NODETYPE_NEQUAL)) { - an_push_error(analyzer, NULL, "node is not typeof binary condition"); + an_push_error(analyzer, NULL, "node is not a binary conditional operator"); return (fzl_an_res_t){.error = true}; } @@ -54,14 +48,14 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node) if (left.type < FZL_TYPE_INT8) { an_push_error(analyzer, cond_node->binary_op.left->token, - "left operand must be number"); + "left operand must have integer type"); return (fzl_an_res_t){.error = true}; } if (left.type < FZL_TYPE_INT8) { an_push_error(analyzer, cond_node->binary_op.left->token, - "right operand must be number"); + "right operand must have integer type"); return (fzl_an_res_t){.error = true}; } } @@ -70,7 +64,7 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node) if (right.type < FZL_TYPE_INT8) { an_push_error(analyzer, cond_node->binary_op.right->token, - "right operand must be an integer"); + "right operand must have integer type"); return (fzl_an_res_t){.error = true}; } @@ -89,12 +83,10 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node) if (!an_is_compatible(left.type, right.type, left.classname, right.classname)) { - snprintf(bincond_problem, sizeof(bincond_problem), - "'%s' and '%s' are incompatible", + snprintf(an_problem, sizeof(an_problem), "'%s' and '%s' are incompatible", an_typetostr(left.type, left.classname), an_typetostr(right.type, right.classname)); - an_push_error(analyzer, cond_node->binary_op.right->token, - bincond_problem); + an_push_error(analyzer, cond_node->binary_op.right->token, an_problem); return (fzl_an_res_t){.error = true}; } } @@ -110,7 +102,7 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node) else if (!an_is_compatible(left.type, right.type, left.classname, right.classname)) { - snprintf(bincond_problem, sizeof(bincond_problem), + snprintf(an_problem, sizeof(an_problem), "equality not supported between %s and %s", an_typetostr(left.type, left.classname), an_typetostr(right.type, right.classname)); diff --git a/src/compiler/analyzer/an_conditional.c b/src/compiler/analyzer/an_conditional.c index 1e5ec96..5a4002d 100644 --- a/src/compiler/analyzer/an_conditional.c +++ b/src/compiler/analyzer/an_conditional.c @@ -4,8 +4,6 @@ #include #include -char cond_problem[256]; - // Analyze conditional statement fzl_an_res_t analyze_conditional(fzl_analyzer_t *analyzer, fzl_node_t *cond) { @@ -14,7 +12,7 @@ fzl_an_res_t analyze_conditional(fzl_analyzer_t *analyzer, fzl_node_t *cond) if (!cond || cond->type != FZL_NODETYPE_CONDITIONAL) { - an_push_error(analyzer, NULL, "provided node is not typeof CONDITIONAL"); + an_push_error(analyzer, NULL, "provided node is a condition"); return (fzl_an_res_t){.error = true}; } @@ -37,9 +35,9 @@ fzl_an_res_t analyze_conditional(fzl_analyzer_t *analyzer, fzl_node_t *cond) if (cond->cond.condition->token->type == FZL_TOKTYPE_BOOL_LITERAL) { - snprintf(cond_problem, sizeof(cond_problem), "condition is always %s", + snprintf(an_problem, sizeof(an_problem), "condition is always %s", (char *)cond->cond.condition->token->value); - an_push_warning(analyzer, cond->cond.condition->token, cond_problem); + an_push_warning(analyzer, cond->cond.condition->token, an_problem); } return (fzl_an_res_t){.error = false, .type = FZL_TYPE_NULL}; diff --git a/src/compiler/analyzer/an_construct.c b/src/compiler/analyzer/an_construct.c index 5c9202d..3529aaf 100644 --- a/src/compiler/analyzer/an_construct.c +++ b/src/compiler/analyzer/an_construct.c @@ -5,8 +5,6 @@ #include #include -char c_problem[256]; - // Analyze class construct fzl_an_res_t analyze_construct(fzl_analyzer_t *analyzer, fzl_node_t *construct) { @@ -15,7 +13,7 @@ fzl_an_res_t analyze_construct(fzl_analyzer_t *analyzer, fzl_node_t *construct) if (!construct || construct->type != FZL_NODETYPE_CONSTRUCT) { - an_push_error(analyzer, NULL, "node is not typeof CONSTRUCT"); + an_push_error(analyzer, NULL, "node is not a construct"); return (fzl_an_res_t){.error = true}; } @@ -30,8 +28,8 @@ fzl_an_res_t analyze_construct(fzl_analyzer_t *analyzer, fzl_node_t *construct) if (!sym_found) { - snprintf(c_problem, sizeof(c_problem), "class '%s' not found", classname); - an_push_error(analyzer, construct->token, c_problem); + snprintf(an_problem, sizeof(an_problem), "class '%s' not found", classname); + an_push_error(analyzer, construct->token, an_problem); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_declaration.c b/src/compiler/analyzer/an_declaration.c index efc0300..4f950dc 100644 --- a/src/compiler/analyzer/an_declaration.c +++ b/src/compiler/analyzer/an_declaration.c @@ -6,11 +6,6 @@ #include #include -char dec_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern fzl_type_t an_toktotype(fzl_token_t *tok); - // Analyze variable/field/argument declaration fzl_an_res_t analyze_declaration(fzl_analyzer_t *analyzer, fzl_node_t *decl) { @@ -19,7 +14,7 @@ fzl_an_res_t analyze_declaration(fzl_analyzer_t *analyzer, fzl_node_t *decl) if (!decl || decl->type != FZL_NODETYPE_DECLARATION) { - an_push_error(analyzer, NULL, "node is not typeof DECLARATION"); + an_push_error(analyzer, NULL, "node is not a declaration"); return (fzl_an_res_t){.error = true}; } @@ -35,12 +30,12 @@ fzl_an_res_t analyze_declaration(fzl_analyzer_t *analyzer, fzl_node_t *decl) if (res != FZL_SYMTABLE_RESULT_OK) { if (res == FZL_SYMTABLE_RESULT_EXISTS) - snprintf(dec_problem, sizeof(dec_problem), - "'%s' already has been declared", name); + snprintf(an_problem, sizeof(an_problem), "'%s' already has been declared", + name); else - snprintf(dec_problem, sizeof(dec_problem), "cannot store '%s'", name); + snprintf(an_problem, sizeof(an_problem), "cannot store '%s'", name); - an_push_error(analyzer, decl->token, dec_problem); + an_push_error(analyzer, decl->token, an_problem); return (fzl_an_res_t){.error = true}; } @@ -57,9 +52,9 @@ fzl_an_res_t analyze_declaration(fzl_analyzer_t *analyzer, fzl_node_t *decl) if (!class_found || class.node->type != FZL_NODETYPE_CLASS) { - snprintf(dec_problem, sizeof(dec_problem), "class '%s' does not exists", + snprintf(an_problem, sizeof(an_problem), "class '%s' does not exists", (char *)decl->var.type->value); - an_push_error(analyzer, decl->var.type, dec_problem); + an_push_error(analyzer, decl->var.type, an_problem); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_field.c b/src/compiler/analyzer/an_field.c index 29fea9c..e231f5d 100644 --- a/src/compiler/analyzer/an_field.c +++ b/src/compiler/analyzer/an_field.c @@ -7,11 +7,6 @@ #include #include -char field_problem[256]; - -// defined in `compiler/analyzer/utility.c` -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) { @@ -20,7 +15,7 @@ fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) if (!field || field->type != FZL_NODETYPE_FIELD) { - an_push_error(analyzer, NULL, "node is not typeof FIELD"); + an_push_error(analyzer, NULL, "node is not field access"); return (fzl_an_res_t){.error = true}; } @@ -30,9 +25,9 @@ fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) if (parent.type != FZL_TYPE_OBJECT || parent.classname == NULL) { - snprintf(field_problem, sizeof(field_problem), - "access to non-object value"); - an_push_error(analyzer, field->token, field_problem); + snprintf(an_problem, sizeof(an_problem), "access to non-object value (%s)", + an_typetostr(parent.type, parent.classname)); + an_push_error(analyzer, field->token, an_problem); return (fzl_an_res_t){.error = true}; } @@ -48,9 +43,9 @@ fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) if (!sym_found) { - snprintf(field_problem, sizeof(field_problem), "class '%s' not found", + snprintf(an_problem, sizeof(an_problem), "class '%s' not found", parent.classname); - an_push_error(analyzer, field->parent->token, field_problem); + an_push_error(analyzer, field->parent->token, an_problem); return (fzl_an_res_t){.error = true}; } @@ -67,9 +62,9 @@ fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) if (field_node == NULL) { - snprintf(field_problem, sizeof(field_problem), - "field '%s.%s' does not exists", parent.classname, field_name); - an_push_error(analyzer, field->memb.field->token, field_problem); + snprintf(an_problem, sizeof(an_problem), "field '%s.%s' does not exists", + parent.classname, field_name); + an_push_error(analyzer, field->memb.field->token, an_problem); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_function.c b/src/compiler/analyzer/an_function.c index e2f619c..a555fed 100644 --- a/src/compiler/analyzer/an_function.c +++ b/src/compiler/analyzer/an_function.c @@ -7,11 +7,6 @@ #include #include -char fn_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern fzl_type_t an_toktotype(fzl_token_t *tok); - fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) { if (!analyzer) @@ -19,7 +14,7 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) if (!fn_node || fn_node->type != FZL_NODETYPE_FUNCTION) { - an_push_error(analyzer, NULL, "node is not typeof FUNCTION"); + an_push_error(analyzer, NULL, "node is not a function"); return (fzl_an_res_t){.error = true}; } @@ -63,7 +58,7 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) if (strcmp(argname, "this") == 0 && i > 0) { an_push_error(analyzer, decl->token, - "manual declaration of 'this' is not allowed"); + "manual declaration of 'this' is not allowed in methods"); an_fin_ctx(analyzer); return (fzl_an_res_t){.error = true}; } @@ -87,10 +82,10 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) { if (putres == FZL_SYMTABLE_RESULT_EXISTS) { - snprintf(fn_problem, sizeof(fn_problem), + snprintf(an_problem, sizeof(an_problem), "method '%s.%s' already has been declared", classname, (char *)fn_node->fn.name->value); - an_push_error(analyzer, fn_node->token, fn_problem); + an_push_error(analyzer, fn_node->token, an_problem); } else an_push_error(analyzer, fn_node->token, "failed to store method"); @@ -111,10 +106,10 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node) { if (putres == FZL_SYMTABLE_RESULT_EXISTS) { - snprintf(fn_problem, sizeof(fn_problem), + snprintf(an_problem, sizeof(an_problem), "function '%s' already has been declared", (char *)fn_node->fn.name->value); - an_push_error(analyzer, fn_node->token, fn_problem); + an_push_error(analyzer, fn_node->token, an_problem); } else an_push_error(analyzer, fn_node->token, "failed to store function"); diff --git a/src/compiler/analyzer/an_identifier.c b/src/compiler/analyzer/an_identifier.c index a56c2cd..da80f41 100644 --- a/src/compiler/analyzer/an_identifier.c +++ b/src/compiler/analyzer/an_identifier.c @@ -3,8 +3,6 @@ #include #include -char id_problem[256]; - // Analyze identifier fzl_an_res_t analyze_identifier(fzl_analyzer_t *analyzer, fzl_node_t *id) { @@ -13,7 +11,7 @@ fzl_an_res_t analyze_identifier(fzl_analyzer_t *analyzer, fzl_node_t *id) if (!id || id->type != FZL_NODETYPE_IDENTIFIER) { - an_push_error(analyzer, NULL, "provided node is not typeof IDENTIFIER"); + an_push_error(analyzer, NULL, "node is not an identifier"); return (fzl_an_res_t){.error = true}; } @@ -28,9 +26,9 @@ fzl_an_res_t analyze_identifier(fzl_analyzer_t *analyzer, fzl_node_t *id) if (!sym_found) { - snprintf(id_problem, sizeof(id_problem), "cannot find symbol '%s'", + snprintf(an_problem, sizeof(an_problem), "cannot find symbol '%s'", symname); - an_push_error(analyzer, id->token, id_problem); + an_push_error(analyzer, id->token, an_problem); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_loop.c b/src/compiler/analyzer/an_loop.c index 3568233..d2e1aa7 100644 --- a/src/compiler/analyzer/an_loop.c +++ b/src/compiler/analyzer/an_loop.c @@ -7,11 +7,6 @@ #include #include -char loop_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern fzl_type_t an_toktotype(fzl_token_t *tok); - // Init block analysis result typedef struct { @@ -386,11 +381,11 @@ fzl_an_res_t analyze_loop(fzl_analyzer_t *analyzer, fzl_node_t *loop_node) if (init_data.name && cond_data.varname && strcmp(init_data.name, cond_data.varname) != 0) { - snprintf(loop_problem, sizeof(loop_problem), + snprintf(an_problem, sizeof(an_problem), "'%s' is used in condition but '%s' is declared. Maybe there is " "mistake?", cond_data.varname, init_data.name); - an_push_warning(analyzer, loop_node->loop.cond->token, loop_problem); + an_push_warning(analyzer, loop_node->loop.cond->token, an_problem); } } @@ -409,35 +404,35 @@ fzl_an_res_t analyze_loop(fzl_analyzer_t *analyzer, fzl_node_t *loop_node) if (step_data.changing_var && cond_data.varname && strcmp(step_data.changing_var, cond_data.varname) != 0) { - snprintf(loop_problem, sizeof(loop_problem), + snprintf(an_problem, sizeof(an_problem), "changing '%s' but condition checking '%s'", step_data.changing_var, cond_data.varname); - an_push_warning(analyzer, loop_node->loop.step->token, loop_problem); + an_push_warning(analyzer, loop_node->loop.step->token, an_problem); } if (cond_data.type == COND_TYPE_VAR_GREATER && step_data.dir == STEP_DIR_TYPE_INCREASE) { - snprintf(loop_problem, sizeof(loop_problem), + snprintf(an_problem, sizeof(an_problem), "'%s' is increasing while condition is 'greater than'", step_data.changing_var); - an_push_warning(analyzer, loop_node->loop.step->token, loop_problem); + an_push_warning(analyzer, loop_node->loop.step->token, an_problem); } else if (cond_data.type == COND_TYPE_VAR_LESS && step_data.dir == STEP_DIR_TYPE_DECREASE) { - snprintf(loop_problem, sizeof(loop_problem), + snprintf(an_problem, sizeof(an_problem), "'%s' is decreasing while condition is 'less than'", step_data.changing_var); - an_push_warning(analyzer, loop_node->loop.step->token, loop_problem); + an_push_warning(analyzer, loop_node->loop.step->token, an_problem); } else if ((cond_data.type == COND_TYPE_VAR_LESS || cond_data.type == COND_TYPE_VAR_GREATER) && step_data.dir == STEP_DIR_TYPE_STALL) { - snprintf(loop_problem, sizeof(loop_problem), "'%s' is stalled", + snprintf(an_problem, sizeof(an_problem), "'%s' is stalled", cond_data.varname); - an_push_warning(analyzer, loop_node->loop.step->token, loop_problem); + an_push_warning(analyzer, loop_node->loop.step->token, an_problem); } } } diff --git a/src/compiler/analyzer/an_return.c b/src/compiler/analyzer/an_return.c index 032e04e..543bc6f 100644 --- a/src/compiler/analyzer/an_return.c +++ b/src/compiler/analyzer/an_return.c @@ -1,16 +1,9 @@ -#include "common/fzl_types.h" +#include #include #include #include #include -char ret_problem[256]; - -// defined in `compiler/analyzer/utility.c` -extern bool an_is_compatible(fzl_type_t a, fzl_type_t b, char *ac, char *bc); -extern fzl_type_t an_toktotype(fzl_token_t *tok); -extern char *an_typetostr(fzl_type_t type, char *classname); - // Analyze return statement fzl_an_res_t analyze_return(fzl_analyzer_t *analyzer, fzl_node_t *ret_node) { @@ -19,7 +12,7 @@ fzl_an_res_t analyze_return(fzl_analyzer_t *analyzer, fzl_node_t *ret_node) if (!ret_node || ret_node->type != FZL_NODETYPE_RETURN) { - an_push_error(analyzer, NULL, "node is not typeof RETURN"); + an_push_error(analyzer, NULL, "node is not a return statement"); return (fzl_an_res_t){.error = false}; } @@ -32,10 +25,22 @@ fzl_an_res_t analyze_return(fzl_analyzer_t *analyzer, fzl_node_t *ret_node) fnctx = fnctx->parent; } + fzl_an_ctx_t *classctx = analyzer->ctx; + while (classctx != NULL) + { + if (classctx && classctx->type == FZL_AN_CTX_TYPE_CLASS) + break; + + classctx = classctx->parent; + } + + bool is_in_method = + classctx != NULL && classctx->type == FZL_AN_CTX_TYPE_CLASS; + if (!fnctx || fnctx->type != FZL_AN_CTX_TYPE_FUNCTION) { an_push_error(analyzer, ret_node->token, - "cannot use 'return' outside function"); + "cannot use 'return' outside the function"); return (fzl_an_res_t){.error = true}; } @@ -49,8 +54,20 @@ fzl_an_res_t analyze_return(fzl_analyzer_t *analyzer, fzl_node_t *ret_node) { if (ret_node->ret.value == NULL) { - an_push_error(analyzer, ret_node->token, - "return must be used with value in this function"); + if (is_in_method) + { + snprintf(an_problem, sizeof(an_problem), + "cannot return null as method '%s.%s' have return type '%s'", + classctx->classname, (char *)fnctx->fn->fn.name->value, + rettype_str); + } + else + { + snprintf(an_problem, sizeof(an_problem), + "cannot return null as function '%s' have return type '%s'", + (char *)fnctx->fn->fn.name->value, rettype_str); + } + an_push_error(analyzer, ret_node->token, an_problem); return (fzl_an_res_t){.error = true}; } @@ -60,10 +77,21 @@ fzl_an_res_t analyze_return(fzl_analyzer_t *analyzer, fzl_node_t *ret_node) if (!an_is_compatible(ret_res.type, rettype, ret_res.classname, classname)) { - snprintf(ret_problem, sizeof(ret_problem), - "expected 'return <%s>' instead of 'return <%s>'", rettype_str, - an_typetostr(ret_res.type, ret_res.classname)); - an_push_error(analyzer, ret_node->token, ret_problem); + if (is_in_method) + { + snprintf(an_problem, sizeof(an_problem), + "method '%s.%s' is expecting return type '%s', got '%s'", + classctx->classname, (char *)fnctx->fn->fn.name->value, + rettype_str, an_typetostr(ret_res.type, ret_res.classname)); + } + else + { + snprintf(an_problem, sizeof(an_problem), + "function '%s' is expecting return type '%s', got '%s'", + (char *)fnctx->fn->fn.name->value, rettype_str, + an_typetostr(ret_res.type, ret_res.classname)); + } + an_push_error(analyzer, ret_node->token, an_problem); return (fzl_an_res_t){.error = true}; } } diff --git a/src/compiler/analyzer/an_unarycond.c b/src/compiler/analyzer/an_unarycond.c index 29123dc..3a7cc68 100644 --- a/src/compiler/analyzer/an_unarycond.c +++ b/src/compiler/analyzer/an_unarycond.c @@ -10,7 +10,7 @@ fzl_an_res_t analyze_unarycond(fzl_analyzer_t *analyzer, fzl_node_t *unary) if (!unary || unary->type != FZL_NODETYPE_NOT) { - an_push_error(analyzer, NULL, "node is not typeof unary condition"); + an_push_error(analyzer, NULL, "node is not an unary condition operator"); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/analyzer/an_unarymath.c b/src/compiler/analyzer/an_unarymath.c index 6df52a5..3f592aa 100644 --- a/src/compiler/analyzer/an_unarymath.c +++ b/src/compiler/analyzer/an_unarymath.c @@ -12,7 +12,7 @@ fzl_an_res_t analyze_unarymath(fzl_analyzer_t *analyzer, fzl_node_t *unary) if (!unary || (unary->type != FZL_NODETYPE_UNARY_MINUS && unary->type != FZL_NODETYPE_UNARY_PLUS)) { - an_push_error(analyzer, NULL, "node is not typeof unary math"); + an_push_error(analyzer, NULL, "node is not an unary math operator"); return (fzl_an_res_t){.error = true}; } diff --git a/src/compiler/fzl_analyzer.c b/src/compiler/fzl_analyzer.c index b35d0cc..9b4603f 100644 --- a/src/compiler/fzl_analyzer.c +++ b/src/compiler/fzl_analyzer.c @@ -14,6 +14,8 @@ size_t aerrors_top; char awarnings[256][256]; size_t awarnings_top; +char an_problem[256]; + fzl_analyzer_t *fzl_mkanalyzer(fzl_node_t *node) { if (!node) diff --git a/src/compiler/utils/fzl_linked.c b/src/compiler/utils/fzl_linked.c index 409455b..26a6f10 100644 --- a/src/compiler/utils/fzl_linked.c +++ b/src/compiler/utils/fzl_linked.c @@ -51,7 +51,7 @@ bool fzl_linked_add_files(fzl_linked_t *l, char **files, size_t files_count) rewind(fd); source = malloc(file_sz + 1); - fread(source, file_sz, 1, fd); + fread(source, file_sz, 1, fd); // NOTE: add red bytes check fclose(fd); source[file_sz] = 0; diff --git a/src/vm/fzl_vm.c b/src/vm/fzl_vm.c index 0e94957..c3e4552 100644 --- a/src/vm/fzl_vm.c +++ b/src/vm/fzl_vm.c @@ -50,7 +50,8 @@ fzl_vm_t *fzl_mkvm(const char *filepath) } char hdr[5]; - fread(hdr, sizeof(char), 5, fd); + fread(hdr, sizeof(char), 5, + fd); // NOTE: add red bytes check (also for freads below) if (memcmp(hdr, expect_hdr, 5) != 0) { snprintf(last_err, sizeof(last_err), "magic check error");