feat: implement extern block analyzer
This commit is contained in:
@@ -50,6 +50,7 @@ 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_extern.c
|
||||
src/compiler/analyzer/an_externfn.c
|
||||
src/compiler/analyzer/an_field.c
|
||||
src/compiler/analyzer/an_function.c
|
||||
|
||||
@@ -11,7 +11,8 @@ 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_type_t an_toktotype(fzl_analyzer_t *analyzer, fzl_token_t *tok,
|
||||
bool *sym_found);
|
||||
|
||||
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);
|
||||
@@ -36,6 +37,7 @@ 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_res_t analyze_extern(fzl_analyzer_t *analyzer, fzl_node_t *extern_node);
|
||||
|
||||
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);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -49,10 +50,19 @@ fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node)
|
||||
|
||||
if (fnctx && fnctx->type == FZL_AN_CTX_TYPE_FUNCTION)
|
||||
{
|
||||
fzl_type_t rettype = an_toktotype(fnctx->fn->fn.type);
|
||||
bool found = false;
|
||||
fzl_type_t rettype = an_toktotype(analyzer, fnctx->fn->fn.type, &found);
|
||||
char *classname = NULL;
|
||||
char *rettype_str = an_typetostr(rettype, classname);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)fnctx->fn->fn.type->value);
|
||||
an_push_error(analyzer, fnctx->fn->fn.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (rettype == FZL_TYPE_OBJECT)
|
||||
classname = (char *)fnctx->fn->fn.type->value;
|
||||
|
||||
|
||||
@@ -177,8 +177,18 @@ fzl_an_res_t analyze_call(fzl_analyzer_t *analyzer, fzl_node_t *call_node)
|
||||
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);
|
||||
bool found = false;
|
||||
fzl_type_t req_type = an_toktotype(analyzer, arg->var.type, &found);
|
||||
char *req_classname = NULL;
|
||||
|
||||
if (!found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)arg->var.type->value);
|
||||
an_push_error(analyzer, arg->var.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (req_type == FZL_TYPE_OBJECT)
|
||||
req_classname = arg->var.type->value;
|
||||
|
||||
@@ -226,9 +236,18 @@ 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);
|
||||
bool type_found = false;
|
||||
fzl_type_t type = an_toktotype(analyzer, sym.node->fn.type, &type_found);
|
||||
char *classname = sym.classname;
|
||||
|
||||
if (!type_found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)sym.node->fn.type->value);
|
||||
an_push_error(analyzer, sym.node->fn.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (tmp_method_name != NULL)
|
||||
{
|
||||
free(tmp_method_name);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Analyzer main function
|
||||
@@ -15,6 +16,14 @@ 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_EXTERN:
|
||||
res = analyze_extern(analyzer, node);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_EXTERN_FN:
|
||||
res = analyze_externfn(analyzer, node);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_REFERENCE:
|
||||
res = analyze_ref(analyzer, node);
|
||||
break;
|
||||
@@ -24,7 +33,7 @@ fzl_an_res_t analyze_common(fzl_analyzer_t *analyzer, fzl_node_t *node)
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_ALIAS:
|
||||
res.type = an_toktotype(node->token);
|
||||
res.type = an_toktotype(analyzer, node->token, NULL);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_HANDLE:
|
||||
|
||||
@@ -20,14 +20,23 @@ fzl_an_res_t analyze_declaration(fzl_analyzer_t *analyzer, fzl_node_t *decl)
|
||||
}
|
||||
|
||||
char *name = (char *)decl->var.identifier->token->value;
|
||||
fzl_type_t type = an_toktotype(decl->var.type);
|
||||
bool type_found = false;
|
||||
fzl_type_t type = an_toktotype(analyzer, decl->var.type, &type_found);
|
||||
|
||||
if (!type_found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)decl->var.type->value);
|
||||
an_push_error(analyzer, decl->var.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
char *classname = NULL;
|
||||
if (type == FZL_TYPE_OBJECT)
|
||||
classname = decl->var.type->value;
|
||||
|
||||
fzl_symtable_res_t res =
|
||||
fzl_symt_put(analyzer->symbols[analyzer->symbols_top - 1], decl, name,
|
||||
an_toktotype(decl->var.type), 0);
|
||||
fzl_symtable_res_t res = fzl_symt_put(
|
||||
analyzer->symbols[analyzer->symbols_top - 1], decl, name, type, 0);
|
||||
if (res != FZL_SYMTABLE_RESULT_OK)
|
||||
{
|
||||
if (res == FZL_SYMTABLE_RESULT_EXISTS)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Analyze extern block definition
|
||||
fzl_an_res_t analyze_extern(fzl_analyzer_t *analyzer, fzl_node_t *extern_node)
|
||||
{
|
||||
if (!analyzer)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
|
||||
if (!extern_node || extern_node->type != FZL_NODETYPE_EXTERN)
|
||||
{
|
||||
an_push_error(analyzer, NULL, "node is not an extern block");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (extern_node->ext.typedefs_count < 1 && extern_node->ext.fns_count < 1)
|
||||
an_push_warning(analyzer, extern_node->token, "extern is empty");
|
||||
|
||||
for (size_t i = 0; i < extern_node->ext.typedefs_count; i++)
|
||||
{
|
||||
fzl_node_t *node = extern_node->ext.typedefs[i];
|
||||
fzl_an_res_t res = analyze_common(analyzer, node);
|
||||
if (res.error)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
|
||||
if (node->type != FZL_NODETYPE_TYPEDEF &&
|
||||
node->type != FZL_NODETYPE_EXTERN_FN)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem),
|
||||
"unexpected statement '%s' inside extern block",
|
||||
(char *)node->token->value);
|
||||
an_push_error(analyzer, node->token, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < extern_node->ext.fns_count; i++)
|
||||
{
|
||||
fzl_an_res_t res = analyze_common(analyzer, extern_node->ext.fns[i]);
|
||||
if (res.error)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
return (fzl_an_res_t){
|
||||
.error = false, .type = FZL_TYPE_NULL, .classname = NULL};
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "common/fzl_types.h"
|
||||
#include "compiler/fzl_parser.h"
|
||||
#include "compiler/fzl_token.h"
|
||||
#include "compiler/utils/fzl_symtable.h"
|
||||
#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>
|
||||
@@ -20,6 +20,8 @@ fzl_an_res_t analyze_externfn(fzl_analyzer_t *analyzer, fzl_node_t *externfn)
|
||||
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]);
|
||||
@@ -70,6 +72,8 @@ fzl_an_res_t analyze_externfn(fzl_analyzer_t *analyzer, fzl_node_t *externfn)
|
||||
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};
|
||||
}
|
||||
|
||||
@@ -69,8 +69,19 @@ fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
fzl_type_t field_type = an_toktotype(field_node->var.type);
|
||||
char *classname = NULL;
|
||||
bool type_found = false;
|
||||
fzl_type_t field_type =
|
||||
an_toktotype(analyzer, field_node->var.type, &type_found);
|
||||
|
||||
if (!type_found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)field_node->var.type->value);
|
||||
an_push_error(analyzer, field_node->var.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
char *classname = NULL;
|
||||
if (field_type == FZL_TYPE_OBJECT)
|
||||
classname = field_node->var.type->value;
|
||||
|
||||
|
||||
@@ -38,8 +38,18 @@ fzl_an_res_t analyze_function(fzl_analyzer_t *analyzer, fzl_node_t *fn_node)
|
||||
ctx = ctx->parent;
|
||||
}
|
||||
|
||||
fzl_type_t rettype = an_toktotype(fn_node->fn.type);
|
||||
bool type_found = false;
|
||||
fzl_type_t rettype = an_toktotype(analyzer, fn_node->fn.type, &type_found);
|
||||
char *classname = NULL;
|
||||
|
||||
if (!type_found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)fn_node->fn.type->value);
|
||||
an_push_error(analyzer, fn_node->fn.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (rettype == FZL_TYPE_OBJECT)
|
||||
classname = (char *)fn_node->fn.type->value;
|
||||
|
||||
|
||||
@@ -49,9 +49,18 @@ init_analysis check_init(fzl_analyzer_t *analyzer, fzl_node_t *init)
|
||||
}
|
||||
else if (init->type == FZL_NODETYPE_DECLARATION)
|
||||
{
|
||||
char *name = init->var.identifier->token->value;
|
||||
fzl_type_t type = an_toktotype(init->var.type);
|
||||
char *name = init->var.identifier->token->value;
|
||||
|
||||
bool type_found = false;
|
||||
fzl_type_t type = an_toktotype(analyzer, init->var.type, &type_found);
|
||||
char *classname = NULL;
|
||||
|
||||
if (!type_found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)init->var.type->value);
|
||||
}
|
||||
|
||||
if (type == FZL_TYPE_OBJECT)
|
||||
classname = init->var.type->value;
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ 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)
|
||||
if (!ref_node || ref_node->type != FZL_NODETYPE_REFERENCE)
|
||||
{
|
||||
an_push_error(analyzer, NULL, "node is not a structure");
|
||||
an_push_error(analyzer, NULL, "node is not a reference");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Analyze return statement
|
||||
@@ -45,8 +46,18 @@ fzl_an_res_t analyze_return(fzl_analyzer_t *analyzer, fzl_node_t *ret_node)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
fzl_type_t rettype = an_toktotype(fnctx->fn->fn.type);
|
||||
bool type_found = false;
|
||||
fzl_type_t rettype = an_toktotype(analyzer, fnctx->fn->fn.type, &type_found);
|
||||
char *classname = NULL;
|
||||
|
||||
if (!type_found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found",
|
||||
(char *)fnctx->fn->fn.type->value);
|
||||
an_push_error(analyzer, fnctx->fn->fn.type, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (rettype == FZL_TYPE_OBJECT)
|
||||
classname = (char *)fnctx->fn->fn.type->value;
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ fzl_an_res_t analyze_struct(fzl_analyzer_t *analyzer, fzl_node_t *struct_node)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
an_nest_ctx(analyzer, FZL_AN_CTX_TYPE_UNNECESSARY);
|
||||
|
||||
if (struct_node->structure.entries_count < 1)
|
||||
{
|
||||
an_push_warning(analyzer, struct_node->token, "empty structure");
|
||||
@@ -47,6 +49,8 @@ fzl_an_res_t analyze_struct(fzl_analyzer_t *analyzer, fzl_node_t *struct_node)
|
||||
}
|
||||
}
|
||||
|
||||
an_fin_ctx(analyzer);
|
||||
|
||||
return (fzl_an_res_t){
|
||||
.error = false, .type = FZL_TYPE_STRUCT, .classname = NULL};
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@ fzl_an_res_t analyze_typedef(fzl_analyzer_t *analyzer, fzl_node_t *td_node)
|
||||
|
||||
fzl_nodetype_t type = td_node->typedefinition.type->type;
|
||||
if (type != FZL_NODETYPE_ALIAS && type != FZL_NODETYPE_STRUCT &&
|
||||
type != FZL_NODETYPE_HANDLE)
|
||||
type != FZL_NODETYPE_HANDLE && type != FZL_NODETYPE_REFERENCE)
|
||||
{
|
||||
an_push_error(analyzer, td_node->token,
|
||||
"only alias, structure and handle are allowed in type "
|
||||
"definition value");
|
||||
an_push_error(
|
||||
analyzer, td_node->token,
|
||||
"only alias, structure, reference and handle are allowed in type "
|
||||
"definition value");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// Check compatibility between A and B types (and classnames)
|
||||
@@ -79,13 +82,30 @@ char *an_typetostr(fzl_type_t type, char *classname)
|
||||
}
|
||||
|
||||
// Convert type token to type
|
||||
fzl_type_t an_toktotype(fzl_token_t *tok)
|
||||
fzl_type_t an_toktotype(fzl_analyzer_t *analyzer, fzl_token_t *tok,
|
||||
bool *sym_found)
|
||||
{
|
||||
if (!tok)
|
||||
return FZL_TYPE_NULL;
|
||||
|
||||
if (tok->type == FZL_TOKTYPE_NAME)
|
||||
return FZL_TYPE_OBJECT;
|
||||
{
|
||||
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], tok->value, &sym)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (sym_found)
|
||||
*sym_found = found;
|
||||
|
||||
return found ? sym.type : FZL_TYPE_NULL;
|
||||
}
|
||||
|
||||
if (sym_found)
|
||||
*sym_found = true;
|
||||
|
||||
if (strcmp(tok->value, "null") == 0)
|
||||
return FZL_TYPE_NULL;
|
||||
|
||||
Reference in New Issue
Block a user