fix: clear fn return type value

This commit is contained in:
samsonium
2026-10-17 21:24:21 +03:00
parent 8c33464656
commit c0c90f4f1a
2 changed files with 63 additions and 74 deletions
+1 -1
View File
@@ -815,7 +815,7 @@ fzl_node_t *parse_function(fzl_parser_t *parser)
return NULL;
}
fzl_token_t *type;
fzl_token_t *type = NULL;
if (is(parser, FZL_TOKTYPE_TYPE) || is(parser, FZL_TOKTYPE_NAME))
type = consume(parser);
+62 -73
View File
@@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
char *null_name = "<null>";
char wlast_err[256];
fzl_walker_t *fzl_mkwalker(fzl_node_t *root)
@@ -105,8 +106,11 @@ static bool is_compatible(fzl_type_t t1, fzl_type_t t2, char *c1, char *c2)
{
if (t1 == FZL_TYPE_OBJECT || t2 == FZL_TYPE_OBJECT)
{
return t1 == FZL_TYPE_OBJECT && t2 == FZL_TYPE_OBJECT &&
(strcmp(c1, c2) == 0);
bool classes_compatible = strcmp(c1, c2) == 0 ||
strcmp(c1, null_name) == 0 ||
strcmp(c2, null_name) == 0;
return t1 == FZL_TYPE_OBJECT && t2 == FZL_TYPE_OBJECT && classes_compatible;
}
if (t1 == t2)
@@ -290,44 +294,34 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
case FZL_NODETYPE_FIELD:
{
fzl_sym_t sym;
bool exists = false;
for (ssize_t i = walker->sym_top - 1; i >= 0; i--)
if ((exists = fzl_symt_get(walker->syms[i],
node->memb.parent->token->value, &sym)))
break;
fzl_walk_res_t parent_res = walk(walker, node->memb.parent);
if (parent_res.error)
return parent_res;
if (!exists)
if (parent_res.type != FZL_TYPE_OBJECT || !parent_res.classname)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': cannot find symbol '%s' at %ld:%ld",
node->token->filename, (char *)node->token->value,
node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
if (!sym.classname)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': '%s' is not an object (at %ld:%ld)",
node->token->filename, sym.name, node->token->ln,
node->token->cn);
fzl_token_t *tok = node->memb.parent->token;
snprintf(
wlast_err, sizeof(wlast_err),
"'%s': cannot access field '%s' on non-object type at %ld:%ld",
tok->filename, (char *)node->memb.field->token->value, tok->ln,
tok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
fzl_ctable_t *ct = NULL;
for (size_t i = 0; i < walker->classes_count; i++)
{
if (strcmp(sym.classname, walker->classes[i]->name) == 0)
if (strcmp(parent_res.classname, walker->classes[i]->name) == 0)
{
ct = walker->classes[i];
break;
}
}
fzl_token_t *tok = node->memb.parent->token;
if (!ct)
{
fzl_token_t *tok = node->memb.parent->token;
snprintf(wlast_err, sizeof(wlast_err),
"'%s': access to unknown class '%s' at %ld:%ld",
tok->filename, (char *)tok->value, tok->ln, tok->cn);
@@ -351,20 +345,17 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': cannot find field '%s' in class '%s' at %ld:%ld",
ftok->filename, (char *)ftok->value, (char *)tok->value,
ftok->filename, (char *)ftok->value, parent_res.classname,
ftok->ln, ftok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
fzl_walk_res_t parent_res = walk(walker, node->memb.parent);
if (parent_res.error)
return parent_res;
push_op(walker, FZL_OPCODE_GET_FIELD);
push_word(walker, ctf.slot_index);
current_res = (fzl_walk_res_t){
.type = ctf.type, .error = false, .classname = sym.classname};
current_res = (fzl_walk_res_t){.type = ctf.type,
.error = false,
.classname = parent_res.classname};
break;
}
@@ -483,7 +474,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (retres.error)
return retres;
if (!is_compatible(retres.type, tok_to_type(walker->ctx->fn->fn.type),
fzl_node_t *fn_node = walker->ctx->fn;
if (!is_compatible(retres.type, tok_to_type(fn_node->fn.type),
retres.classname, walker->ctx->fn->fn.type->value))
{
snprintf(
@@ -807,80 +799,68 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
else 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;
fzl_sym_t res;
bool found = false;
for (ssize_t i = walker->sym_top - 1; i >= 0; i--)
if ((found = fzl_symt_get(walker->syms[i],
parent_node->token->value, &res)))
break;
fzl_walk_res_t parent_res = walk(walker, parent_node);
if (parent_res.error)
return parent_res;
if (!found)
if (parent_res.type != FZL_TYPE_OBJECT || !parent_res.classname)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': access to unknown object '%s' at %ld:%ld",
node->token->filename, (char *)parent_node->token->value,
node->token->ln, node->token->cn);
"'%s': cannot call method on non-object type at %ld:%ld",
parent_node->token->filename, parent_node->token->ln,
parent_node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
if (res.type != FZL_TYPE_OBJECT || !res.classname)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': name '%s' is not an object (at %ld:%ld)",
parent_node->token->filename,
(char *)parent_node->token->value,
parent_node->token->ln, parent_node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
found = false;
char *classname = parent_res.classname;
bool class_exists = false;
for (size_t i = 0; i < walker->classes_count; i++)
{
if (strcmp(walker->classes[i]->name, res.classname) == 0)
if (strcmp(classname, walker->classes[i]->name) == 0)
{
found = true;
class_exists = true;
break;
}
}
if (!found)
if (!class_exists)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': class '%s' not found at %ld:%ld",
node->token->filename, res.classname, node->token->ln,
node->token->cn);
"'%s': class '%s' not found (at %ld:%ld)",
parent_node->token->filename, classname,
parent_node->token->ln, parent_node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
char *classname = res.classname;
size_t classlen = strlen(res.classname);
size_t fnlen = strlen(node->call.callee->token->value);
size_t classlen = strlen(classname);
size_t fnlen = strlen(method_node->token->value);
char *methodname = malloc(classlen + fnlen + 2);
strcpy(methodname, res.classname);
strcpy(methodname, classname);
strcpy((methodname + classlen + 1),
node->call.callee->token->value);
methodname[classlen] = '_';
methodname[classlen + fnlen + 1] = 0;
found = false;
fzl_sym_t fn_sym;
bool found_method = false;
for (ssize_t i = walker->sym_top - 1; i >= 0; i--)
if ((found = fzl_symt_get(walker->syms[i], methodname, &res)))
if ((found_method =
fzl_symt_get(walker->syms[i], methodname, &fn_sym)))
break;
if (!found)
if (!found_method)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': class '%s' has no method '%s' at %ld:%ld",
node->token->filename, classname,
(char *)node->call.callee->token->value, node->token->ln,
node->token->cn);
free(methodname);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
fzl_walk_res_t parent = walk(walker, parent_node);
if (parent.error)
return parent;
free(methodname);
if (node->call.args_count > 0)
{
@@ -893,10 +873,11 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
}
push_op(walker, FZL_OPCODE_CALL);
push_word(walker, res.ip);
push_word(walker, fn_sym.ip);
current_res = (fzl_walk_res_t){
.type = res.type, .error = false, .classname = res.classname};
current_res = (fzl_walk_res_t){.type = fn_sym.type,
.error = false,
.classname = fn_sym.classname};
}
}
break;
@@ -931,6 +912,14 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
push_word(walker, val);
current_res = (fzl_walk_res_t){.type = FZL_TYPE_BOOL, .error = false};
}
else if (node->token->type == FZL_TOKTYPE_NULL_LITERAL)
{
fzl_token_t *tok = node->token;
push_op(walker, FZL_OPCODE_PUSHNUM);
push_word(walker, 0);
current_res = (fzl_walk_res_t){
.type = FZL_TYPE_OBJECT, .error = false, .classname = null_name};
}
break;
case FZL_NODETYPE_ADD: