wip: working on analyzer

- Feat: add binary math analysis
- Fix: check for function context in block analysis
- Feat: add 'break' analysis
- Fix: few fixes in call analysis
- Feat: add class analysis
- Feat: add construct analysis
- Feat: add declaration analysis
- Feat: add field analysis
- Feat: add function analysis
- Feat: add loop analysis
- Ref: updated utilities and context functions
This commit is contained in:
samsonium
2026-10-27 05:18:36 +03:00
parent d7630dbb6a
commit 25991c6f15
17 changed files with 1094 additions and 30 deletions
+71 -5
View File
@@ -32,7 +32,7 @@ char *resolve_callee(fzl_analyzer_t *analyzer, fzl_node_t *callee, bool *method)
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)
if (!tmp_method_name)
{
an_push_error(analyzer, callee->token,
"failed to allocate space for method name");
@@ -61,10 +61,7 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
return (fzl_an_res_t){.error = true};
}
fzl_node_t *callee = call_node->call.callee;
fzl_an_res_t callee_res = analyze_common(analyzer, callee);
if (callee_res.error)
return (fzl_an_res_t){.error = true};
fzl_node_t *callee = call_node->call.callee;
bool is_method = false;
char *callee_name = resolve_callee(analyzer, callee, &is_method);
@@ -73,11 +70,46 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
an_push_error(analyzer, callee->token, "expression is not callable");
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = true};
}
if (strcmp(callee_name, "printline") == 0 || strcmp(callee_name, "exit") == 0)
{
if (call_node->call.args_count != 1)
{
snprintf(call_problem, sizeof(call_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);
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = true};
}
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){
.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--)
@@ -91,6 +123,13 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
snprintf(call_problem, sizeof(call_problem), "cannot resolve symbol '%s'",
callee_name);
an_push_error(analyzer, call_node->token, call_problem);
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = true};
}
@@ -99,6 +138,13 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
snprintf(call_problem, sizeof(call_problem), "'%s' is not callable",
callee_name);
an_push_error(analyzer, call_node->token, call_problem);
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = true};
}
@@ -108,6 +154,13 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
"expected %zu argument(s) while %zu is specified",
sym.node->fn.args_count, call_node->call.args_count);
an_push_error(analyzer, call_node->token, call_problem);
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = true};
}
@@ -122,6 +175,13 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
an_typetostr(req.type, req.classname),
an_typetostr(got.type, got.classname));
an_push_error(analyzer, call_node->token, call_problem);
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = true};
}
}
@@ -129,5 +189,11 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
fzl_type_t type = an_toktotype(sym.node->fn.type);
char *classname = sym.classname;
if (tmp_method_name != NULL)
{
free(tmp_method_name);
tmp_method_name = NULL;
}
return (fzl_an_res_t){.error = false, .type = type, .classname = classname};
}