wip: working on dynamic linking
- Feat: add analyzers for: - external functions - reference - structures - type definitions - Feat: add new nodes to debug print (ast)
This commit is contained in:
@@ -50,12 +50,16 @@ 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_externfn.c
|
||||
src/compiler/analyzer/an_field.c
|
||||
src/compiler/analyzer/an_function.c
|
||||
src/compiler/analyzer/an_identifier.c
|
||||
src/compiler/analyzer/an_loop.c
|
||||
src/compiler/analyzer/an_ref.c
|
||||
src/compiler/analyzer/an_return.c
|
||||
src/compiler/analyzer/an_strfmt.c
|
||||
src/compiler/analyzer/an_struct.c
|
||||
src/compiler/analyzer/an_typedef.c
|
||||
src/compiler/analyzer/an_unarycond.c
|
||||
src/compiler/analyzer/an_unarymath.c
|
||||
src/compiler/parser/pa_and.c
|
||||
|
||||
@@ -7,6 +7,8 @@ typedef enum
|
||||
FZL_TYPE_OBJECT,
|
||||
|
||||
FZL_TYPE_EXTERN_FN,
|
||||
FZL_TYPE_HANDLE,
|
||||
FZL_TYPE_STRUCT,
|
||||
|
||||
FZL_TYPE_STRING,
|
||||
FZL_TYPE_CHAR,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -31,6 +32,10 @@ fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node);
|
||||
fzl_an_res_t analyze_unarycond(fzl_analyzer_t *analyzer, fzl_node_t *unary);
|
||||
fzl_an_res_t analyze_assign(fzl_analyzer_t *analyzer, fzl_node_t *assign_node);
|
||||
fzl_an_res_t analyze_strfmt(fzl_analyzer_t *analyzer, fzl_node_t *strfmt_node);
|
||||
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_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);
|
||||
|
||||
@@ -15,6 +15,26 @@ 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_REFERENCE:
|
||||
res = analyze_ref(analyzer, node);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_STRUCT:
|
||||
res = analyze_struct(analyzer, node);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_ALIAS:
|
||||
res.type = an_toktotype(node->token);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_HANDLE:
|
||||
res.type = FZL_TYPE_HANDLE;
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_TYPEDEF:
|
||||
res = analyze_typedef(analyzer, node);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_FMT_STRING:
|
||||
res = analyze_strfmt(analyzer, node);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "common/fzl_types.h"
|
||||
#include "compiler/fzl_parser.h"
|
||||
#include "compiler/fzl_token.h"
|
||||
#include "compiler/utils/fzl_symtable.h"
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/internals/analyzer.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};
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
return (fzl_an_res_t){
|
||||
.error = false, .type = FZL_TYPE_EXTERN_FN, .classname = NULL};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Analyze reference
|
||||
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)
|
||||
{
|
||||
an_push_error(analyzer, NULL, "node is not a structure");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
char *refto = (char *)ref_node->token->value;
|
||||
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], refto, &sym)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
snprintf(an_problem, sizeof(an_problem), "cannot find name '%s'", refto);
|
||||
an_push_error(analyzer, ref_node->token, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
return (fzl_an_res_t){
|
||||
.error = false, .type = FZL_TYPE_HANDLE, .classname = refto};
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Analyze structure definition
|
||||
fzl_an_res_t analyze_struct(fzl_analyzer_t *analyzer, fzl_node_t *struct_node)
|
||||
{
|
||||
if (!analyzer)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
|
||||
if (!struct_node || struct_node->type != FZL_NODETYPE_STRUCT)
|
||||
{
|
||||
an_push_error(analyzer, NULL, "node is not a structure");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (struct_node->structure.entries_count < 1)
|
||||
{
|
||||
an_push_warning(analyzer, struct_node->token, "empty structure");
|
||||
return (fzl_an_res_t){.error = false};
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < struct_node->structure.entries_count; i++)
|
||||
{
|
||||
fzl_node_t *entry = struct_node->structure.entries[i];
|
||||
if (entry->type != FZL_NODETYPE_DECLARATION &&
|
||||
entry->type != FZL_NODETYPE_IDENTIFIER)
|
||||
{
|
||||
an_push_error(
|
||||
analyzer, entry->token,
|
||||
"structure can contain only declarations and another structures");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
fzl_an_res_t res = analyze_common(analyzer, entry);
|
||||
if (res.error)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
|
||||
if (res.type == FZL_TYPE_OBJECT)
|
||||
{
|
||||
an_push_error(analyzer, entry->token,
|
||||
"cannot store object inside struct");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
}
|
||||
|
||||
return (fzl_an_res_t){
|
||||
.error = false, .type = FZL_TYPE_STRUCT, .classname = NULL};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Analyze type definition
|
||||
fzl_an_res_t analyze_typedef(fzl_analyzer_t *analyzer, fzl_node_t *td_node)
|
||||
{
|
||||
if (!analyzer)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
|
||||
if (!td_node || td_node->type != FZL_NODETYPE_TYPEDEF)
|
||||
{
|
||||
an_push_error(analyzer, NULL, "node is not a type definition");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
fzl_an_res_t res = analyze_common(analyzer, td_node->typedefinition.type);
|
||||
if (res.error)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
|
||||
fzl_nodetype_t type = td_node->typedefinition.type->type;
|
||||
if (type != FZL_NODETYPE_ALIAS && type != FZL_NODETYPE_STRUCT &&
|
||||
type != FZL_NODETYPE_HANDLE)
|
||||
{
|
||||
an_push_error(analyzer, td_node->token,
|
||||
"only alias, structure and handle are allowed in type "
|
||||
"definition value");
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
fzl_symtable_res_t putres =
|
||||
fzl_symt_put(analyzer->symbols[0], td_node,
|
||||
td_node->typedefinition.typename, res.type, 0);
|
||||
if (putres != FZL_SYMTABLE_RESULT_OK)
|
||||
{
|
||||
if (putres == FZL_SYMTABLE_RESULT_EXISTS)
|
||||
snprintf(an_problem, sizeof(an_problem),
|
||||
"symbol '%s' already has been declared",
|
||||
td_node->typedefinition.typename);
|
||||
else
|
||||
snprintf(an_problem, sizeof(an_problem), "cannot store symbol '%s'",
|
||||
td_node->typedefinition.typename);
|
||||
|
||||
an_push_error(analyzer, td_node->token, an_problem);
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
return (fzl_an_res_t){.error = false, .type = res.type, .classname = NULL};
|
||||
}
|
||||
@@ -32,6 +32,52 @@ void print_node(fzl_node_t *node, int level)
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case FZL_NODETYPE_EXTERN:
|
||||
printf("%s Extern bindings to library '%s':\n", levelbuf,
|
||||
node->ext.libname);
|
||||
printf("-%s Types:\n", levelbuf);
|
||||
for (size_t i = 0; i < node->ext.typedefs_count; i++)
|
||||
print_node(node->ext.typedefs[i], level + 2);
|
||||
printf("-%s Functions:\n", levelbuf);
|
||||
for (size_t i = 0; i < node->ext.fns_count; i++)
|
||||
print_node(node->ext.fns[i], level + 2);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_EXTERN_FN:
|
||||
printf("%s External function '%s' (original name %s), rettype '%s':\n",
|
||||
levelbuf, node->ext_fn.name, node->ext_fn.original_name,
|
||||
(char *)node->ext_fn.type->value);
|
||||
printf("-%s Arguments:\n", levelbuf);
|
||||
for (size_t i = 0; i < node->ext_fn.args_count; i++)
|
||||
print_node(node->ext_fn.args[i], level + 2);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_REFERENCE:
|
||||
printf("%s Reference (pointer type) to '%s'\n", levelbuf,
|
||||
(char *)node->token->value);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_STRUCT:
|
||||
printf("%s Structure '%s' (original name %s):\n", levelbuf,
|
||||
(char *)node->token->value, node->structure.original_name);
|
||||
for (size_t i = 0; i < node->structure.entries_count; i++)
|
||||
print_node(node->structure.entries[i], level + 1);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_ALIAS:
|
||||
printf("%s Type alias to '%s'\n", levelbuf, (char *)node->token->value);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_HANDLE:
|
||||
printf("%s Opaque pointer (handle)\n", levelbuf);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_TYPEDEF:
|
||||
printf("%s Type definition '%s':\n", levelbuf,
|
||||
node->typedefinition.typename);
|
||||
print_node(node->typedefinition.type, level + 1);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_UNARY_MINUS:
|
||||
printf("%s Unary '-':\n", levelbuf);
|
||||
print_node(node->unary_op.operand, level + 1);
|
||||
|
||||
Reference in New Issue
Block a user