Compare commits
2
Commits
358ede4c8c
...
c0bd0d95b2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0bd0d95b2 | ||
|
|
26decf2626 |
@@ -0,0 +1,77 @@
|
||||
#ifndef FZL_GENERATOR_H
|
||||
#define FZL_GENERATOR_H
|
||||
|
||||
#include <common/fzl_extern.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/utils/fzl_const_pool.h>
|
||||
#include <compiler/utils/fzl_ctable.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Generator context type
|
||||
typedef enum
|
||||
{
|
||||
FZL_GEN_CTX_TYPE_UNECCESSARY,
|
||||
FZL_GEN_CTX_TYPE_FUNCTION,
|
||||
FZL_GEN_CTX_TYPE_CLASS,
|
||||
FZL_GEN_CTX_TYPE_LOOP
|
||||
} fzl_gen_ctx_type_t;
|
||||
|
||||
// Generator context descriptor
|
||||
typedef struct fzl_gen_ctx
|
||||
{
|
||||
fzl_gen_ctx_type_t type;
|
||||
struct fzl_gen_ctx *parent;
|
||||
|
||||
size_t level;
|
||||
|
||||
union
|
||||
{
|
||||
fzl_node_t *function;
|
||||
|
||||
struct
|
||||
{
|
||||
size_t breaks[256];
|
||||
size_t breaks_count;
|
||||
} loop;
|
||||
};
|
||||
} fzl_gen_ctx_t;
|
||||
|
||||
// Generator descriptor
|
||||
typedef struct
|
||||
{
|
||||
fzl_node_t *root;
|
||||
fzl_const_hash_pool_t *consts;
|
||||
fzl_gen_ctx_t *ctx;
|
||||
|
||||
size_t *ops;
|
||||
size_t ops_count;
|
||||
size_t ops_remainder;
|
||||
|
||||
fzl_symtable_t *syms[256];
|
||||
size_t syms_top;
|
||||
|
||||
fzl_ctable_t *classes[64];
|
||||
size_t classes_count;
|
||||
|
||||
fzl_extern_lib_t extern_libs[64];
|
||||
size_t extern_libs_count;
|
||||
|
||||
fzl_extern_type_t extern_types[256];
|
||||
size_t extern_types_count;
|
||||
|
||||
fzl_extern_fn_t extern_fns[256];
|
||||
size_t extern_fns_count;
|
||||
} fzl_gen_t;
|
||||
|
||||
// Allocate new generator
|
||||
fzl_gen_t *fzl_mkgen(fzl_node_t *root);
|
||||
|
||||
// Run program generation
|
||||
bool fzl_gen_run(fzl_gen_t *gen);
|
||||
|
||||
// Free generator
|
||||
void fzl_freegen(fzl_gen_t *gen);
|
||||
|
||||
#endif // FZL_GENERATOR_H
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef INTERNALS_GEN_H
|
||||
#define INTERNALS_GEN_H
|
||||
|
||||
#include <common/fzl_opcodes.h>
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/utils/fzl_const_pool.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern char *null_name;
|
||||
|
||||
bool gen_resolve_name(fzl_gen_t *gen, char *name, fzl_sym_t *sym);
|
||||
bool gen_resolve_type(fzl_gen_t *gen, fzl_token_t *tok, fzl_type_t *t, char *c);
|
||||
bool gen_is_types_compatible(fzl_type_t t1, fzl_type_t t2, char *c1, char *c2);
|
||||
size_t gen_add_const(fzl_gen_t *gen, fzl_const_t c);
|
||||
void gen_op(fzl_gen_t *gen, fzl_opcode_t opcode);
|
||||
void gen_word(fzl_gen_t *gen, size_t word);
|
||||
|
||||
fzl_gen_ctx_t *gen_ctx(fzl_gen_t *gen, fzl_gen_ctx_type_t type,
|
||||
fzl_node_t *node);
|
||||
fzl_gen_ctx_t *gen_fin_ctx(fzl_gen_t *gen);
|
||||
|
||||
bool gen_common(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_extern(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_externfn(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_reference(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_struct(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_alias(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_handle(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_typedef(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_fmtstr(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_break(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_loop(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_class(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_construct(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_field(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_fn(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_return(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_not(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_compare(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_or_and(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_condition(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_unary_plus(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_unary_minus(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_identifier(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_block(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_call(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_literal(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_math(fzl_gen_t *gen, fzl_node_t *node);
|
||||
bool gen_assign(fzl_gen_t *gen, fzl_node_t *node);
|
||||
|
||||
#endif // FZL_INTERNALS_GEN_H
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_analyzer.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/analyzer.h>
|
||||
@@ -48,5 +49,9 @@ fzl_an_res_t analyze_typedef(fzl_analyzer_t *analyzer, fzl_node_t *td_node)
|
||||
return (fzl_an_res_t){.error = true};
|
||||
}
|
||||
|
||||
if (res.type == FZL_TYPE_STRUCT || res.type == FZL_TYPE_HANDLE)
|
||||
fzl_symt_setobjclass(analyzer->symbols[0], td_node->typedefinition.typename,
|
||||
td_node->typedefinition.typename);
|
||||
|
||||
return (fzl_an_res_t){.error = false, .type = res.type, .classname = NULL};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "compiler/fzl_parser.h"
|
||||
#include "compiler/utils/fzl_ctable.h"
|
||||
#include "compiler/utils/fzl_symtable.h"
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <compiler/utils/fzl_const_pool.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
fzl_gen_t *fzl_mkgen(fzl_node_t *root)
|
||||
{
|
||||
if (!root)
|
||||
return NULL;
|
||||
|
||||
fzl_gen_t *gen = malloc(sizeof(fzl_gen_t));
|
||||
if (!gen)
|
||||
return NULL;
|
||||
|
||||
memset(gen, 0, sizeof(fzl_gen_t));
|
||||
|
||||
gen->root = root;
|
||||
gen->consts = fzl_mkconstpool();
|
||||
if (!gen->consts)
|
||||
{
|
||||
free(gen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gen->ops_remainder = 2;
|
||||
gen->ops = malloc(gen->ops_remainder * sizeof(size_t));
|
||||
|
||||
gen->ctx = gen_ctx(gen, FZL_GEN_CTX_TYPE_UNECCESSARY, NULL);
|
||||
if (!gen->ctx)
|
||||
{
|
||||
fzl_consts_pool_free(gen->consts);
|
||||
free(gen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gen;
|
||||
}
|
||||
|
||||
bool fzl_gen_run(fzl_gen_t *gen)
|
||||
{
|
||||
if (!gen)
|
||||
return false;
|
||||
|
||||
fzl_node_t *current = gen->root;
|
||||
while (current != NULL)
|
||||
{
|
||||
if (!gen_common(gen, current))
|
||||
return false;
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fzl_freegen(fzl_gen_t *gen)
|
||||
{
|
||||
if (!gen)
|
||||
return;
|
||||
|
||||
if (gen->consts)
|
||||
fzl_consts_pool_free(gen->consts);
|
||||
|
||||
if (gen->ops)
|
||||
free(gen->ops);
|
||||
|
||||
if (gen->syms_top > 0)
|
||||
for (ssize_t i = gen->syms_top - 1; i >= 0; i--)
|
||||
fzl_freesymt(gen->syms[i]);
|
||||
|
||||
if (gen->classes_count > 0)
|
||||
for (ssize_t i = gen->classes_count - 1; i >= 0; i--)
|
||||
fzl_freectable(gen->classes[i]);
|
||||
|
||||
free(gen);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "compiler/fzl_parser.h"
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Nest context
|
||||
fzl_gen_ctx_t *gen_ctx(fzl_gen_t *gen, fzl_gen_ctx_type_t type,
|
||||
fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !type)
|
||||
return NULL;
|
||||
|
||||
fzl_gen_ctx_t *ctx = malloc(sizeof(fzl_gen_ctx_t));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
memset(ctx, 0, sizeof(fzl_gen_ctx_t));
|
||||
|
||||
fzl_symtable_t *symt = fzl_mksymt();
|
||||
if (!symt)
|
||||
{
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gen->syms[gen->syms_top++] = symt;
|
||||
|
||||
size_t level = 0;
|
||||
fzl_gen_ctx_t *parent = gen->ctx;
|
||||
while (parent != NULL)
|
||||
{
|
||||
level++;
|
||||
parent = parent->parent;
|
||||
}
|
||||
|
||||
ctx->type = type;
|
||||
ctx->level = level;
|
||||
ctx->parent = gen->ctx;
|
||||
|
||||
if (type == FZL_GEN_CTX_TYPE_FUNCTION)
|
||||
{
|
||||
if (node->type == FZL_NODETYPE_FUNCTION)
|
||||
ctx->function = node;
|
||||
else
|
||||
{
|
||||
fzl_freesymt(symt);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gen->ctx = ctx;
|
||||
|
||||
return gen->ctx;
|
||||
}
|
||||
|
||||
fzl_gen_ctx_t *gen_fin_ctx(fzl_gen_t *gen)
|
||||
{
|
||||
if (!gen)
|
||||
return NULL;
|
||||
|
||||
fzl_gen_ctx_t *ctx = gen->ctx;
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
fzl_symtable_t *sym = gen->syms[--gen->syms_top];
|
||||
if (sym)
|
||||
fzl_freesymt(sym);
|
||||
|
||||
gen->ctx = ctx->parent;
|
||||
free(ctx);
|
||||
|
||||
return gen->ctx;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Check ops length and resize if needed
|
||||
bool ops_check_size(fzl_gen_t *gen)
|
||||
{
|
||||
if (!gen)
|
||||
return false;
|
||||
|
||||
if (gen->ops_count >= gen->ops_remainder)
|
||||
{
|
||||
gen->ops_remainder *= 2;
|
||||
size_t *newops = realloc(gen->ops, gen->ops_remainder * sizeof(size_t));
|
||||
if (!newops)
|
||||
return false;
|
||||
|
||||
gen->ops = newops;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Push opcode
|
||||
void gen_op(fzl_gen_t *gen, fzl_opcode_t opcode)
|
||||
{
|
||||
if (!gen)
|
||||
return;
|
||||
|
||||
if (!ops_check_size(gen))
|
||||
return;
|
||||
|
||||
gen->ops[gen->ops_count++] = opcode;
|
||||
}
|
||||
|
||||
// Push word
|
||||
void gen_word(fzl_gen_t *gen, size_t word)
|
||||
{
|
||||
if (!gen)
|
||||
return;
|
||||
|
||||
if (!ops_check_size(gen))
|
||||
return;
|
||||
|
||||
gen->ops[gen->ops_count++] = word;
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <compiler/utils/fzl_const_pool.h>
|
||||
#include <compiler/utils/fzl_symtable.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// Resolve name in symbol tables
|
||||
bool gen_resolve_name(fzl_gen_t *gen, char *name, fzl_sym_t *sym)
|
||||
{
|
||||
if (!gen || !name || !sym)
|
||||
return NULL;
|
||||
|
||||
bool found = false;
|
||||
for (ssize_t i = gen->syms_top - 1; i >= 0; i--)
|
||||
{
|
||||
if ((found = fzl_symt_get(gen->syms[i], name, sym)))
|
||||
break;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// Resolve type and return if was resolved or not
|
||||
bool gen_resolve_type(fzl_gen_t *gen, fzl_token_t *tok, fzl_type_t *t, char *c)
|
||||
{
|
||||
if (!gen || !tok || !t)
|
||||
return false;
|
||||
|
||||
if (tok->type == FZL_TOKTYPE_NAME)
|
||||
{
|
||||
char *name = (char *)tok->value;
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
fzl_sym_t sym;
|
||||
if (!gen_resolve_name(gen, name, &sym))
|
||||
return false;
|
||||
|
||||
if (sym.node && sym.node->type == FZL_NODETYPE_CLASS)
|
||||
{
|
||||
*t = FZL_TYPE_OBJECT;
|
||||
if (c)
|
||||
c = sym.classname;
|
||||
}
|
||||
else if (sym.node && sym.node->type == FZL_NODETYPE_TYPEDEF)
|
||||
{
|
||||
*t = sym.type;
|
||||
if (c)
|
||||
c = sym.classname;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(tok->value, "null") == 0)
|
||||
*t = FZL_TYPE_NULL;
|
||||
else if (strcmp(tok->value, "str") == 0)
|
||||
*t = FZL_TYPE_STRING;
|
||||
else if (strcmp(tok->value, "bool") == 0)
|
||||
*t = FZL_TYPE_BOOL;
|
||||
else if (strcmp(tok->value, "char") == 0)
|
||||
*t = FZL_TYPE_CHAR;
|
||||
|
||||
else if (strcmp(tok->value, "uint") == 0)
|
||||
*t = FZL_TYPE_UINT;
|
||||
else if (strcmp(tok->value, "u8") == 0)
|
||||
*t = FZL_TYPE_UINT8;
|
||||
else if (strcmp(tok->value, "u16") == 0)
|
||||
*t = FZL_TYPE_UINT16;
|
||||
else if (strcmp(tok->value, "u32") == 0)
|
||||
*t = FZL_TYPE_UINT32;
|
||||
else if (strcmp(tok->value, "u64") == 0)
|
||||
*t = FZL_TYPE_UINT64;
|
||||
|
||||
else if (strcmp(tok->value, "int") == 0)
|
||||
*t = FZL_TYPE_INT;
|
||||
else if (strcmp(tok->value, "i8") == 0)
|
||||
*t = FZL_TYPE_INT8;
|
||||
else if (strcmp(tok->value, "i16") == 0)
|
||||
*t = FZL_TYPE_INT16;
|
||||
else if (strcmp(tok->value, "i32") == 0)
|
||||
*t = FZL_TYPE_INT32;
|
||||
else if (strcmp(tok->value, "i64") == 0)
|
||||
*t = FZL_TYPE_INT64;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if left and right types are compatible
|
||||
bool gen_is_types_compatible(fzl_type_t t1, fzl_type_t t2, char *c1, char *c2)
|
||||
{
|
||||
if (t1 == FZL_TYPE_OBJECT && t2 == FZL_TYPE_OBJECT)
|
||||
{
|
||||
if (!c1 || !c2)
|
||||
return false;
|
||||
|
||||
if (strcmp(c1, null_name) == 0 || strcmp(c2, null_name) == 0)
|
||||
return true;
|
||||
|
||||
return strcmp(c1, c2) == 0;
|
||||
}
|
||||
|
||||
if ((t1 == FZL_TYPE_HANDLE && t2 == FZL_TYPE_HANDLE) ||
|
||||
(t1 == FZL_TYPE_STRUCT && t2 == FZL_TYPE_STRUCT))
|
||||
{
|
||||
if (!c1 || !c2)
|
||||
return false;
|
||||
|
||||
return strcmp(c1, c2) == 0;
|
||||
}
|
||||
|
||||
if (t1 == t2)
|
||||
return true;
|
||||
|
||||
if (t1 >= FZL_TYPE_INT8 && t2 >= FZL_TYPE_INT8)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add new constant to constants table
|
||||
size_t gen_add_const(fzl_gen_t *gen, fzl_const_t c)
|
||||
{
|
||||
if (!gen)
|
||||
return 0;
|
||||
|
||||
return fzl_consts_pool_add(gen->consts, c);
|
||||
}
|
||||
Reference in New Issue
Block a user