Files
fz-lang/src/compiler/analyzer/an_externfn.c
T

80 lines
2.3 KiB
C

#include <common/fzl_types.h>
#include <compiler/fzl_analyzer.h>
#include <compiler/fzl_parser.h>
#include <compiler/fzl_token.h>
#include <compiler/internals/analyzer.h>
#include <compiler/utils/fzl_symtable.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
// 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};
}
an_nest_ctx(analyzer, FZL_AN_CTX_TYPE_UNNECESSARY);
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};
}
an_fin_ctx(analyzer);
return (fzl_an_res_t){
.error = false, .type = FZL_TYPE_EXTERN_FN, .classname = NULL};
}