diff --git a/include/compiler/fzl_gen.h b/include/compiler/fzl_gen.h new file mode 100644 index 0000000..b75f94f --- /dev/null +++ b/include/compiler/fzl_gen.h @@ -0,0 +1,77 @@ +#ifndef FZL_GENERATOR_H +#define FZL_GENERATOR_H + +#include +#include +#include +#include +#include +#include +#include + +// 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 diff --git a/include/compiler/internals/gen.h b/include/compiler/internals/gen.h new file mode 100644 index 0000000..b4ea3dd --- /dev/null +++ b/include/compiler/internals/gen.h @@ -0,0 +1,56 @@ +#ifndef INTERNALS_GEN_H +#define INTERNALS_GEN_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 diff --git a/src/compiler/fzl_gen.c b/src/compiler/fzl_gen.c new file mode 100644 index 0000000..9479f52 --- /dev/null +++ b/src/compiler/fzl_gen.c @@ -0,0 +1,83 @@ +#include "compiler/fzl_parser.h" +#include "compiler/utils/fzl_ctable.h" +#include "compiler/utils/fzl_symtable.h" +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/src/compiler/generator/context.c b/src/compiler/generator/context.c new file mode 100644 index 0000000..3c3a32d --- /dev/null +++ b/src/compiler/generator/context.c @@ -0,0 +1,77 @@ +#include "compiler/fzl_parser.h" +#include +#include +#include +#include +#include +#include + +// 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; +} diff --git a/src/compiler/generator/op.c b/src/compiler/generator/op.c new file mode 100644 index 0000000..ba8aa87 --- /dev/null +++ b/src/compiler/generator/op.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +// 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; +} diff --git a/src/compiler/generator/utility.c b/src/compiler/generator/utility.c new file mode 100644 index 0000000..3a9cc5f --- /dev/null +++ b/src/compiler/generator/utility.c @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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); +}