116 lines
4.0 KiB
C
116 lines
4.0 KiB
C
#include <common/fzl_types.h>
|
|
#include <compiler/fzl_analyzer.h>
|
|
#include <compiler/fzl_parser.h>
|
|
#include <compiler/internals/analyzer.h>
|
|
#include <stdio.h>
|
|
|
|
// Analyze binary conditional nodes
|
|
fzl_an_res_t analyze_condition(fzl_analyzer_t *analyzer, fzl_node_t *cond_node)
|
|
{
|
|
if (!analyzer)
|
|
return (fzl_an_res_t){.error = true};
|
|
|
|
if (!cond_node || (cond_node->type != FZL_NODETYPE_OR &&
|
|
cond_node->type != FZL_NODETYPE_AND &&
|
|
cond_node->type != FZL_NODETYPE_LESS &&
|
|
cond_node->type != FZL_NODETYPE_LESS_EQUAL &&
|
|
cond_node->type != FZL_NODETYPE_GREATER &&
|
|
cond_node->type != FZL_NODETYPE_GREATER_EQUAL &&
|
|
cond_node->type != FZL_NODETYPE_EQUAL &&
|
|
cond_node->type != FZL_NODETYPE_NEQUAL))
|
|
{
|
|
an_push_error(analyzer, NULL, "node is not a binary conditional operator");
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
|
|
fzl_an_res_t left = analyze_common(analyzer, cond_node->binary_op.left);
|
|
if (left.error)
|
|
return (fzl_an_res_t){.error = true};
|
|
|
|
fzl_an_res_t right = analyze_common(analyzer, cond_node->binary_op.right);
|
|
if (right.error)
|
|
return (fzl_an_res_t){.error = true};
|
|
|
|
if (cond_node->type == FZL_NODETYPE_OR || cond_node->type == FZL_NODETYPE_AND)
|
|
{
|
|
if (left.type != FZL_TYPE_BOOL)
|
|
an_push_warning(analyzer, cond_node->binary_op.left->token,
|
|
"left operand is not resulting with boolean type");
|
|
|
|
if (right.type != FZL_TYPE_BOOL)
|
|
an_push_warning(analyzer, cond_node->binary_op.right->token,
|
|
"right operand is not resulting with boolean type");
|
|
}
|
|
else if (cond_node->type == FZL_NODETYPE_LESS ||
|
|
cond_node->type == FZL_NODETYPE_LESS_EQUAL ||
|
|
cond_node->type == FZL_NODETYPE_GREATER ||
|
|
cond_node->type == FZL_NODETYPE_GREATER_EQUAL)
|
|
{
|
|
if (left.type < FZL_TYPE_INT8)
|
|
{
|
|
an_push_error(analyzer, cond_node->binary_op.left->token,
|
|
"left operand must have integer type");
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
|
|
if (left.type < FZL_TYPE_INT8)
|
|
{
|
|
an_push_error(analyzer, cond_node->binary_op.left->token,
|
|
"right operand must have integer type");
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
}
|
|
else if (left.type >= FZL_TYPE_INT8)
|
|
{
|
|
if (right.type < FZL_TYPE_INT8)
|
|
{
|
|
an_push_error(analyzer, cond_node->binary_op.right->token,
|
|
"right operand must have integer type");
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
|
|
return (fzl_an_res_t){
|
|
.error = false, .type = FZL_TYPE_BOOL, .classname = NULL};
|
|
}
|
|
else if (left.type == FZL_TYPE_OBJECT)
|
|
{
|
|
if (!left.classname || !right.classname)
|
|
{
|
|
an_push_error(analyzer, cond_node->binary_op.left->token,
|
|
"unhandled error :(");
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
|
|
if (!an_is_compatible(left.type, right.type, left.classname,
|
|
right.classname))
|
|
{
|
|
snprintf(an_problem, sizeof(an_problem), "'%s' and '%s' are incompatible",
|
|
an_typetostr(left.type, left.classname),
|
|
an_typetostr(right.type, right.classname));
|
|
an_push_error(analyzer, cond_node->binary_op.right->token, an_problem);
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
}
|
|
else if (left.type == FZL_TYPE_STRING)
|
|
{
|
|
if (right.type != FZL_TYPE_STRING)
|
|
{
|
|
an_push_error(analyzer, cond_node->binary_op.right->token,
|
|
"right operand must be a string");
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
}
|
|
else if (!an_is_compatible(left.type, right.type, left.classname,
|
|
right.classname))
|
|
{
|
|
snprintf(an_problem, sizeof(an_problem),
|
|
"equality not supported between %s and %s",
|
|
an_typetostr(left.type, left.classname),
|
|
an_typetostr(right.type, right.classname));
|
|
return (fzl_an_res_t){.error = true};
|
|
}
|
|
|
|
return (fzl_an_res_t){
|
|
.error = false, .type = FZL_TYPE_BOOL, .classname = NULL};
|
|
}
|