wip: working on generator
- Feat: add break handler - Feat: add class handler - Feat: add format string handler - Feat: add loop handler
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Break keyword
|
||||
bool gen_break(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return false;
|
||||
|
||||
fzl_gen_ctx_t *ctx = gen->ctx;
|
||||
while (ctx != NULL)
|
||||
{
|
||||
if (ctx && ctx->type == FZL_GEN_CTX_TYPE_LOOP)
|
||||
break;
|
||||
|
||||
ctx = ctx->parent;
|
||||
}
|
||||
|
||||
if (!ctx || ctx->type != FZL_GEN_CTX_TYPE_LOOP)
|
||||
return false;
|
||||
|
||||
for (size_t i = gen->syms_top - 1; i > ctx->level + 1; i--)
|
||||
gen_op(gen, FZL_OPCODE_RM_ENVTABLE);
|
||||
|
||||
gen_op(gen, FZL_OPCODE_JMP);
|
||||
ctx->loop.breaks[ctx->loop.breaks_count++] = gen->ops_count;
|
||||
gen_word(gen, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Class definition
|
||||
bool gen_class(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return false;
|
||||
|
||||
fzl_gen_ctx_t *ctx = gen_ctx(gen, FZL_GEN_CTX_TYPE_CLASS, node);
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
||||
gen->classes[gen->classes_count] = fzl_mkctable(node->class.name->value);
|
||||
fzl_ctable_t *class = gen->classes[gen->classes_count++];
|
||||
class->name = node->class.name->value;
|
||||
|
||||
for (size_t i = 0; i < node->class.fields_count; i++)
|
||||
{
|
||||
if (class->fields_remainder <= class->fields_count)
|
||||
{
|
||||
class->fields_remainder *= 2;
|
||||
class->fields = realloc(class->fields, class->fields_remainder *
|
||||
sizeof(fzl_ctable_field_t));
|
||||
}
|
||||
|
||||
fzl_type_t type;
|
||||
char typecn[256];
|
||||
memset(typecn, 0, sizeof(typecn));
|
||||
|
||||
bool resolved =
|
||||
gen_resolve_type(gen, node->class.fields[i]->var.type, &type, typecn);
|
||||
if (!resolved)
|
||||
{
|
||||
free(class->fields);
|
||||
return false;
|
||||
}
|
||||
|
||||
class->fields[class->fields_count] = (fzl_ctable_field_t){
|
||||
.name = node->class.fields[i]->var.identifier->token->value,
|
||||
.type = type,
|
||||
.slot_index = class->fields_count++};
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node->class.methods_count; i++)
|
||||
{
|
||||
fzl_node_t *fn = node->class.methods[i];
|
||||
|
||||
size_t classname_len = strlen(class->name);
|
||||
size_t fnname_len = strlen(fn->fn.name->value);
|
||||
char *method_name = malloc(classname_len + fnname_len + 2);
|
||||
|
||||
strcpy(method_name, class->name);
|
||||
method_name[classname_len] = '_';
|
||||
strcpy((method_name + classname_len + 1), fn->fn.name->value);
|
||||
method_name[classname_len + fnname_len + 1] = 0;
|
||||
|
||||
if (fn->fn.name->value)
|
||||
free(fn->fn.name->value);
|
||||
|
||||
fn->fn.name->value = method_name;
|
||||
if (!gen_common(gen, fn))
|
||||
{
|
||||
free(class->fields);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ctx = gen_fin_ctx(gen);
|
||||
if (!ctx)
|
||||
{
|
||||
free(class->fields);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Format string
|
||||
bool gen_fmtstr(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < node->list.entry_count; i++)
|
||||
if (!gen_common(gen, node->list.entries[i]))
|
||||
return false;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_BUILD_STR);
|
||||
gen_word(gen, node->list.entry_count);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// While or for loops
|
||||
bool gen_loop(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return false;
|
||||
|
||||
fzl_gen_ctx_t *ctx = gen_ctx(gen, FZL_GEN_CTX_TYPE_LOOP, node);
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_MK_ENVTABLE);
|
||||
|
||||
if (node->loop.init)
|
||||
if (!gen_common(gen, node->loop.init))
|
||||
return false;
|
||||
|
||||
size_t start_ip = gen->ops_count;
|
||||
if (node->loop.cond)
|
||||
{
|
||||
if (!gen_common(gen, node->loop.cond))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gen_op(gen, FZL_OPCODE_PUSHNUM);
|
||||
gen_word(gen, 1);
|
||||
}
|
||||
|
||||
gen_op(gen, FZL_OPCODE_JZ);
|
||||
ctx->loop.breaks[ctx->loop.breaks_count++] = gen->ops_count;
|
||||
gen_word(gen, 0);
|
||||
|
||||
if (!gen_common(gen, node->loop.body))
|
||||
return false;
|
||||
|
||||
if (node->loop.step)
|
||||
if (!gen_common(gen, node->loop.step))
|
||||
return false;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_JMP);
|
||||
gen_word(gen, start_ip);
|
||||
|
||||
// backpatch `break`s
|
||||
for (size_t i = 0; i < ctx->loop.breaks_count; i++)
|
||||
gen->ops[ctx->loop.breaks[i]] = gen->ops_count;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_RM_ENVTABLE);
|
||||
|
||||
for (size_t i = gen->syms_top - 1; i > ctx->level; i--)
|
||||
fzl_freesymt(gen->syms[--gen->syms_top]);
|
||||
|
||||
ctx = gen_fin_ctx(gen);
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user