123 lines
2.9 KiB
C
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;
|
|
}
|