feat: finish generator
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <compiler/fzl_gen.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
|
||||
// Block definition
|
||||
gen_res_t gen_block(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
fzl_gen_ctx_t *ctx = gen_ctx(gen, FZL_GEN_CTX_TYPE_UNECCESSARY, node);
|
||||
if (!ctx)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_MK_ENVTABLE);
|
||||
if (node->list.entry_count > 0)
|
||||
for (size_t i = 0; i < node->list.entry_count; i++)
|
||||
if (gen_common(gen, node->list.entries[i]).error)
|
||||
return gen_error;
|
||||
|
||||
ctx = gen_fin_ctx(gen);
|
||||
if (!ctx)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_RM_ENVTABLE);
|
||||
|
||||
return gen_ok_null;
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
#include <common/fzl_builtins.h>
|
||||
#include <common/fzl_extern.h>
|
||||
#include <common/fzl_opcodes.h>
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Call definition
|
||||
// NOTE: split by call type (builtin/declared/extern)
|
||||
gen_res_t gen_call(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
// `printline(x)` builtin function
|
||||
if (strcmp(node->token->value, "printline") == 0)
|
||||
{
|
||||
if (node->call.args_count > 0)
|
||||
for (size_t i = 0; i < node->call.args_count; i++)
|
||||
if (gen_common(gen, node->call.args[i]).error)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_CALL_BUILTIN);
|
||||
gen_word(gen, FZL_BUILTIN_PRINTLINE);
|
||||
if (node->call.args_count < 1)
|
||||
return gen_error;
|
||||
|
||||
return gen_ok_null;
|
||||
}
|
||||
|
||||
// `exit(x?)` builtin function
|
||||
if (strcmp(node->token->value, "exit") == 0)
|
||||
{
|
||||
if (node->call.args_count > 0)
|
||||
{
|
||||
for (size_t i = 0; i < node->call.args_count; i++)
|
||||
if (gen_common(gen, node->call.args[i]).error)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_CALL_BUILTIN);
|
||||
gen_word(gen, FZL_BUILTIN_EXIT);
|
||||
if (node->call.args_count < 1)
|
||||
return gen_error;
|
||||
}
|
||||
|
||||
return gen_ok_null;
|
||||
}
|
||||
|
||||
if (node->call.callee->type == FZL_NODETYPE_IDENTIFIER)
|
||||
{
|
||||
if (node->call.args_count > 0)
|
||||
for (size_t i = 0; i < node->call.args_count; i++)
|
||||
if (gen_common(gen, node->call.args[i]).error)
|
||||
return gen_error;
|
||||
|
||||
char *name = (char *)node->token->value;
|
||||
fzl_sym_t sym;
|
||||
bool found = gen_resolve_name(gen, name, &sym);
|
||||
if (!found)
|
||||
return gen_error;
|
||||
|
||||
gen_res_t result;
|
||||
if (sym.node->type == FZL_NODETYPE_EXTERN_FN)
|
||||
{
|
||||
size_t fn_n = 0;
|
||||
fzl_extern_fn_t *fn = NULL;
|
||||
for (size_t i = 0; i < gen->extern_fns_count; i++)
|
||||
{
|
||||
if (strcmp(gen->extern_fns[i].used_name, name) == 0)
|
||||
{
|
||||
fn = &gen->extern_fns[i];
|
||||
fn_n = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fn)
|
||||
return gen_error;
|
||||
|
||||
fzl_type_t rettype;
|
||||
char *rettypecn = NULL;
|
||||
|
||||
if (!fn->has_return)
|
||||
{
|
||||
rettype = FZL_TYPE_NULL;
|
||||
}
|
||||
else if (fn->ret_type.is_primitive)
|
||||
{
|
||||
rettype = fn->ret_type.primitive;
|
||||
}
|
||||
else
|
||||
{
|
||||
fzl_extern_type_t *type = &gen->extern_types[fn->ret_type.type_slot];
|
||||
switch (type->kind)
|
||||
{
|
||||
case FZL_EXTERN_KIND_REF:
|
||||
rettype = FZL_TYPE_HANDLE;
|
||||
rettypecn = type->name;
|
||||
break;
|
||||
|
||||
case FZL_EXTERN_KIND_STRUCT:
|
||||
rettype = FZL_TYPE_STRUCT;
|
||||
rettypecn = type->name;
|
||||
break;
|
||||
|
||||
case FZL_EXTERN_KIND_HANDLE:
|
||||
rettype = FZL_TYPE_HANDLE;
|
||||
rettypecn = type->name;
|
||||
break;
|
||||
|
||||
case FZL_EXTERN_KIND_ALIAS:
|
||||
if (type->alias_target.is_primitive)
|
||||
{
|
||||
rettype = type->alias_target.primitive;
|
||||
}
|
||||
else
|
||||
{
|
||||
fzl_extern_type_t *aliased =
|
||||
&gen->extern_types[type->alias_target.type_slot];
|
||||
switch (aliased->kind)
|
||||
{
|
||||
case FZL_EXTERN_KIND_ALIAS:
|
||||
return gen_error;
|
||||
|
||||
case FZL_EXTERN_KIND_HANDLE:
|
||||
rettype = FZL_TYPE_HANDLE;
|
||||
rettypecn = aliased->name;
|
||||
break;
|
||||
|
||||
case FZL_EXTERN_KIND_STRUCT:
|
||||
rettype = FZL_TYPE_STRUCT;
|
||||
rettypecn = aliased->name;
|
||||
break;
|
||||
|
||||
case FZL_EXTERN_KIND_REF:
|
||||
rettype = FZL_TYPE_HANDLE;
|
||||
rettypecn = aliased->name;
|
||||
break;
|
||||
|
||||
default:
|
||||
return gen_error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gen_op(gen, FZL_OPCODE_CALL_EXTERN);
|
||||
gen_word(gen, fn_n);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = rettype, .classname = rettypecn};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sym.ip)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_CALL);
|
||||
gen_word(gen, sym.ip);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = sym.type, .classname = sym.classname};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (node->call.callee->type == FZL_NODETYPE_FIELD)
|
||||
{
|
||||
fzl_node_t *parent_node = node->call.callee->memb.parent;
|
||||
fzl_node_t *method_node = node->call.callee->memb.field;
|
||||
|
||||
gen_res_t parent_res = gen_common(gen, parent_node);
|
||||
if (parent_res.error)
|
||||
return gen_error;
|
||||
|
||||
if (parent_res.type != FZL_TYPE_OBJECT || !parent_res.classname)
|
||||
return gen_error;
|
||||
|
||||
char *classname = parent_res.classname;
|
||||
bool class_exists = false;
|
||||
for (size_t i = 0; i < gen->classes_count; i++)
|
||||
{
|
||||
if (strcmp(classname, gen->classes[i]->name) == 0)
|
||||
{
|
||||
class_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists)
|
||||
return gen_error;
|
||||
|
||||
size_t classlen = strlen(classname);
|
||||
size_t fnlen = strlen(method_node->token->value);
|
||||
char *methodname = malloc(classlen + fnlen + 2);
|
||||
strcpy(methodname, classname);
|
||||
strcpy((methodname + classlen + 1), node->call.callee->token->value);
|
||||
methodname[classlen] = '_';
|
||||
methodname[classlen + fnlen + 1] = 0;
|
||||
|
||||
fzl_sym_t fn_sym;
|
||||
bool found_method = false;
|
||||
for (ssize_t i = gen->syms_top - 1; i >= 0; i--)
|
||||
if ((found_method = fzl_symt_get(gen->syms[i], methodname, &fn_sym)))
|
||||
break;
|
||||
|
||||
if (!found_method)
|
||||
return gen_error;
|
||||
|
||||
free(methodname);
|
||||
|
||||
if (node->call.args_count > 0)
|
||||
for (size_t i = 0; i < node->call.args_count; i++)
|
||||
if (gen_common(gen, node->call.args[i]).error)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_CALL);
|
||||
gen_word(gen, fn_sym.ip);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = fn_sym.type, .classname = fn_sym.classname};
|
||||
}
|
||||
|
||||
return gen_error;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Comparison operations
|
||||
gen_res_t gen_compare(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
gen_res_t left = gen_common(gen, node->binary_op.left);
|
||||
if (left.error)
|
||||
return left;
|
||||
|
||||
gen_res_t right = gen_common(gen, node->binary_op.right);
|
||||
if (right.error)
|
||||
return right;
|
||||
|
||||
if (!gen_is_types_compatible(left.type, right.type, left.classname,
|
||||
right.classname))
|
||||
return gen_error;
|
||||
|
||||
if (left.type == FZL_TYPE_STRING && right.type == FZL_TYPE_STRING)
|
||||
{
|
||||
switch (node->type)
|
||||
{
|
||||
case FZL_NODETYPE_EQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_EQ_STR);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_NEQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_NEQ_STR);
|
||||
break;
|
||||
|
||||
default:
|
||||
return gen_error;
|
||||
}
|
||||
}
|
||||
else if (left.type == FZL_TYPE_OBJECT && right.type == FZL_TYPE_OBJECT)
|
||||
{
|
||||
switch (node->type)
|
||||
{
|
||||
case FZL_NODETYPE_EQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_EQ_OBJ);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_NEQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_NEQ_OBJ);
|
||||
break;
|
||||
|
||||
default:
|
||||
return gen_error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (node->type)
|
||||
{
|
||||
case FZL_NODETYPE_EQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_EQ);
|
||||
break;
|
||||
case FZL_NODETYPE_NEQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_NEQ);
|
||||
break;
|
||||
case FZL_NODETYPE_LESS:
|
||||
gen_op(gen, FZL_OPCODE_CMP_LT);
|
||||
break;
|
||||
case FZL_NODETYPE_LESS_EQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_LTEQ);
|
||||
break;
|
||||
case FZL_NODETYPE_GREATER:
|
||||
gen_op(gen, FZL_OPCODE_CMP_GT);
|
||||
break;
|
||||
case FZL_NODETYPE_GREATER_EQUAL:
|
||||
gen_op(gen, FZL_OPCODE_CMP_GTEQ);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (gen_res_t){.error = false, .type = FZL_TYPE_BOOL, .classname = NULL};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#include <compiler/internals/gen.h>
|
||||
|
||||
// Conditional operation
|
||||
gen_res_t gen_condition(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
gen_res_t cres = gen_common(gen, node->cond.condition);
|
||||
if (cres.error)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_JZ);
|
||||
|
||||
size_t jz_if = gen->ops_count;
|
||||
gen_word(gen, (uint64_t)0);
|
||||
|
||||
gen_res_t tblock_res = gen_common(gen, node->cond.true_block);
|
||||
if (tblock_res.error)
|
||||
return gen_error;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_JMP);
|
||||
size_t jmp_else = gen->ops_count;
|
||||
gen_word(gen, (uint64_t)0);
|
||||
|
||||
gen->ops[jz_if] = gen->ops_count;
|
||||
|
||||
if (node->cond.else_block)
|
||||
{
|
||||
gen_res_t fblock_res = gen_common(gen, node->cond.else_block);
|
||||
if (fblock_res.error)
|
||||
return gen_error;
|
||||
}
|
||||
|
||||
gen->ops[jmp_else] = gen->ops_count;
|
||||
return gen_ok_null;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
// Variable (or argument) declaration
|
||||
gen_res_t gen_declaration(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
char *name = (char *)node->var.identifier->token->value;
|
||||
fzl_type_t type;
|
||||
char typecn[256];
|
||||
memset(typecn, 0, sizeof(typecn));
|
||||
|
||||
bool resolved = gen_resolve_type(gen, node->var.type, &type, typecn);
|
||||
if (!resolved)
|
||||
return gen_error;
|
||||
|
||||
fzl_ctable_t *ct = NULL;
|
||||
if (type == FZL_TYPE_OBJECT)
|
||||
{
|
||||
for (size_t i = 0; i < gen->classes_count; i++)
|
||||
{
|
||||
if (strcmp(node->var.type->value, gen->classes[i]->name) == 0)
|
||||
{
|
||||
ct = gen->classes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fzl_symtable_res_t res =
|
||||
fzl_symt_put(gen->syms[gen->syms_top - 1], node, name, type, 0);
|
||||
|
||||
if (ct)
|
||||
fzl_symt_setobjclass(gen->syms[gen->syms_top - 1], name, ct->name);
|
||||
|
||||
if (res != FZL_SYMTABLE_RESULT_OK)
|
||||
return gen_error;
|
||||
|
||||
if (fzl_symt_setslot(gen->syms[gen->syms_top - 1], name) < 0)
|
||||
return gen_error;
|
||||
|
||||
fzl_token_t *id_tok = node->var.identifier->token;
|
||||
size_t const_n =
|
||||
gen_add_const(gen, (fzl_const_t){.type = FZL_CONSTTYPE_STRING,
|
||||
.as.string.chars = id_tok->value,
|
||||
.as.string.length = id_tok->value_sz});
|
||||
|
||||
gen_op(gen, FZL_OPCODE_LOADCONST);
|
||||
gen_word(gen, const_n);
|
||||
|
||||
gen_op(gen, FZL_OPCODE_STORE);
|
||||
gen_op(gen, FZL_OPCODE_LOADCONST);
|
||||
gen_word(gen, const_n);
|
||||
|
||||
return (gen_res_t){.error = false, .type = type, .classname = typecn};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <compiler/internals/gen.h>
|
||||
|
||||
// Identifier lookup
|
||||
gen_res_t gen_identifier(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
fzl_sym_t sym;
|
||||
bool exists = false;
|
||||
ssize_t i = gen->syms_top - 1;
|
||||
for (; i >= 0; i--)
|
||||
if ((exists = fzl_symt_get(gen->syms[i], node->token->value, &sym)))
|
||||
break;
|
||||
|
||||
if (!exists)
|
||||
return gen_error;
|
||||
|
||||
if (!sym.slot_set)
|
||||
return gen_error;
|
||||
|
||||
size_t depth = gen->syms_top - 1 - i;
|
||||
gen_op(gen, FZL_OPCODE_LOAD_LOCAL);
|
||||
gen_word(gen, depth);
|
||||
gen_word(gen, sym.slot);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = sym.type, .classname = sym.classname};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
gen_res_t gen_literal(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
if (node->token->type == FZL_TOKTYPE_STR_LITERAL)
|
||||
{
|
||||
size_t n = gen_add_const(
|
||||
gen, (fzl_const_t){.type = FZL_CONSTTYPE_STRING,
|
||||
.as.string.chars = node->token->value,
|
||||
.as.string.length = node->token->value_sz});
|
||||
|
||||
gen_op(gen, FZL_OPCODE_LOADCONST);
|
||||
gen_word(gen, n);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = FZL_TYPE_STRING, .classname = NULL};
|
||||
}
|
||||
|
||||
if (node->token->type == FZL_TOKTYPE_NUM_LITERAL)
|
||||
{
|
||||
gen_op(gen, FZL_OPCODE_PUSHNUM);
|
||||
|
||||
uint64_t num = strtol(node->token->value, NULL, 10);
|
||||
gen_word(gen, num);
|
||||
|
||||
return (gen_res_t){.error = false, .type = FZL_TYPE_INT, .classname = NULL};
|
||||
}
|
||||
|
||||
if (node->token->type == FZL_TOKTYPE_BOOL_LITERAL)
|
||||
{
|
||||
fzl_token_t *tok = node->token;
|
||||
uint64_t val = strcmp(tok->value, "true") == 0 ? 1 : 0;
|
||||
|
||||
gen_op(gen, FZL_OPCODE_PUSHBOOL);
|
||||
gen_word(gen, val);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = FZL_TYPE_BOOL, .classname = NULL};
|
||||
}
|
||||
|
||||
if (node->token->type == FZL_TOKTYPE_NULL_LITERAL)
|
||||
{
|
||||
gen_op(gen, FZL_OPCODE_PUSHNUM);
|
||||
gen_word(gen, 0);
|
||||
gen_op(gen, FZL_OPCODE_DEREFERENCE);
|
||||
|
||||
return (gen_res_t){
|
||||
.error = false, .type = FZL_TYPE_OBJECT, .classname = null_name};
|
||||
}
|
||||
|
||||
return gen_error;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Binary logical operations (and / or)
|
||||
gen_res_t gen_logical(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
gen_res_t left = gen_common(gen, node->binary_op.left);
|
||||
if (left.error)
|
||||
return left;
|
||||
|
||||
gen_res_t right = gen_common(gen, node->binary_op.right);
|
||||
if (right.error)
|
||||
return right;
|
||||
|
||||
if (!gen_is_types_compatible(left.type, right.type, left.classname,
|
||||
right.classname))
|
||||
return gen_error;
|
||||
|
||||
if (node->type == FZL_NODETYPE_AND)
|
||||
gen_op(gen, FZL_OPCODE_AND);
|
||||
else
|
||||
gen_op(gen, FZL_OPCODE_OR);
|
||||
|
||||
return (gen_res_t){.error = false, .type = FZL_TYPE_BOOL, .classname = NULL};
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <common/fzl_types.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Binary math operations
|
||||
gen_res_t gen_math(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
gen_res_t lres = gen_common(gen, node->binary_op.left);
|
||||
if (lres.error)
|
||||
return lres;
|
||||
|
||||
gen_res_t rres = gen_common(gen, node->binary_op.right);
|
||||
if (rres.error)
|
||||
return rres;
|
||||
|
||||
if (lres.type < FZL_TYPE_INT8 || rres.type < FZL_TYPE_INT8)
|
||||
return gen_error;
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case FZL_NODETYPE_ADD:
|
||||
gen_op(gen, FZL_OPCODE_ADD);
|
||||
break;
|
||||
case FZL_NODETYPE_SUB:
|
||||
gen_op(gen, FZL_OPCODE_SUB);
|
||||
break;
|
||||
case FZL_NODETYPE_MUL:
|
||||
gen_op(gen, FZL_OPCODE_MUL);
|
||||
break;
|
||||
case FZL_NODETYPE_DIV:
|
||||
gen_op(gen, FZL_OPCODE_DIV);
|
||||
break;
|
||||
case FZL_NODETYPE_POW:
|
||||
gen_op(gen, FZL_OPCODE_POW);
|
||||
break;
|
||||
case FZL_NODETYPE_MOD:
|
||||
gen_op(gen, FZL_OPCODE_MOD);
|
||||
break;
|
||||
default:
|
||||
return gen_error;
|
||||
}
|
||||
|
||||
return (gen_res_t){.error = false, .type = lres.type, .classname = NULL};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <common/fzl_opcodes.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/internals/gen.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Unary math operations
|
||||
gen_res_t gen_unary_math(fzl_gen_t *gen, fzl_node_t *node)
|
||||
{
|
||||
if (!gen || !node)
|
||||
return gen_error;
|
||||
|
||||
gen_res_t res = gen_common(gen, node->unary_op.operand);
|
||||
if (res.error)
|
||||
return gen_error;
|
||||
|
||||
if (node->type == FZL_NODETYPE_UNARY_MINUS)
|
||||
gen_op(gen, FZL_OPCODE_NEG);
|
||||
|
||||
return (gen_res_t){.error = false, .type = res.type, .classname = NULL};
|
||||
}
|
||||
Reference in New Issue
Block a user