From c0c90f4f1ae77f511fcd76e60878b4e1dfddfa25 Mon Sep 17 00:00:00 2001 From: samsonium Date: Sat, 17 Oct 2026 21:24:21 +0300 Subject: [PATCH] fix: clear fn return type value --- src/compiler/fzl_parser.c | 2 +- src/compiler/fzl_walker.c | 135 +++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 74 deletions(-) diff --git a/src/compiler/fzl_parser.c b/src/compiler/fzl_parser.c index 43154fc..5e403c0 100644 --- a/src/compiler/fzl_parser.c +++ b/src/compiler/fzl_parser.c @@ -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); diff --git a/src/compiler/fzl_walker.c b/src/compiler/fzl_walker.c index 783c629..6095168 100644 --- a/src/compiler/fzl_walker.c +++ b/src/compiler/fzl_walker.c @@ -14,6 +14,7 @@ #include #include +char *null_name = ""; 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: