Files
fz-lang/src/compiler/generator/gen_assign.c
T
2026-11-05 00:04:12 +03:00

123 lines
2.9 KiB
C

#include <compiler/fzl_gen.h>
#include <compiler/fzl_parser.h>
#include <compiler/internals/gen.h>
#include <string.h>
// Assignment to declaration
gen_res_t assign_declaration(fzl_gen_t *gen, fzl_node_t *node)
{
gen_res_t rres = gen_common(gen, node->binary_op.right);
if (rres.error)
return gen_error;
gen_res_t lres = gen_common(gen, node->binary_op.left);
if (lres.error)
return gen_error;
if (!gen_is_types_compatible(rres.type, lres.type, rres.classname,
lres.classname))
return gen_error;
gen_op(gen, FZL_OPCODE_WRITE);
return (gen_res_t){
.error = false, .type = rres.type, .classname = rres.classname};
}
// Assignment to identifier
gen_res_t assign_id(fzl_gen_t *gen, fzl_node_t *node)
{
gen_res_t rres = gen_common(gen, node->binary_op.right);
if (rres.error)
return gen_error;
char *name = (char *)node->binary_op.left->token->value;
fzl_sym_t sym;
bool found = false;
ssize_t i = gen->syms_top - 1;
for (; i >= 0; i--)
if ((found = fzl_symt_get(gen->syms[i], name, &sym)))
break;
if (!found)
return gen_error;
if (!gen_is_types_compatible(sym.type, rres.type, sym.classname,
rres.classname))
return gen_error;
if (!sym.slot_set)
return gen_error;
size_t depth = gen->syms_top - 1 - i;
gen_op(gen, FZL_OPCODE_STORE_LOCAL);
gen_word(gen, depth);
gen_word(gen, sym.slot);
return (gen_res_t){
.error = false, .type = rres.type, .classname = rres.classname};
}
// Assignment to field
gen_res_t assign_field(fzl_gen_t *gen, fzl_node_t *node)
{
gen_res_t rres = gen_common(gen, node->binary_op.right);
if (rres.error)
return gen_error;
fzl_node_t *field_node = node->binary_op.left;
gen_res_t obj_res = gen_common(gen, field_node->memb.parent);
if (obj_res.error)
return gen_error;
fzl_ctable_t *ct = NULL;
for (size_t i = 0; i < gen->classes_count; i++)
{
if (strcmp(obj_res.classname, gen->classes[i]->name) == 0)
{
ct = gen->classes[i];
break;
}
}
if (!ct)
return gen_error;
fzl_ctable_field_t *ctf = NULL;
for (size_t i = 0; i < ct->fields_count; i++)
{
if (strcmp(field_node->memb.field->token->value, ct->fields[i].name) == 0)
{
ctf = &ct->fields[i];
break;
}
}
if (!ctf)
return gen_error;
gen_op(gen, FZL_OPCODE_SET_FIELD);
gen_word(gen, ctf->slot_index);
return (gen_res_t){
.error = false, .type = rres.type, .classname = rres.classname};
}
// Assignment
gen_res_t gen_assign(fzl_gen_t *gen, fzl_node_t *node)
{
if (!gen || !node)
return gen_error;
if (node->binary_op.left->type == FZL_NODETYPE_DECLARATION)
return assign_declaration(gen, node);
if (node->binary_op.left->type == FZL_NODETYPE_IDENTIFIER)
return assign_id(gen, node);
if (node->binary_op.left->type == FZL_NODETYPE_FIELD)
return assign_field(gen, node);
return gen_error;
}