#include #include #include #include #include #include #include // Analyze block fzl_an_res_t analyze_block(fzl_analyzer_t *analyzer, fzl_node_t *block_node) { if (!analyzer) return (fzl_an_res_t){.error = true}; if (!block_node || block_node->type != FZL_NODETYPE_BLOCK) { snprintf(an_problem, sizeof(an_problem), "node is not a block"); an_push_error(analyzer, NULL, an_problem); return (fzl_an_res_t){.error = true}; } an_nest_ctx(analyzer, FZL_AN_CTX_TYPE_UNNECESSARY); bool has_return = false; bool error = false; for (size_t i = 0; i < block_node->list.entry_count; i++) { if (has_return) an_push_warning(analyzer, block_node->list.entries[i]->token, "this statement will never execute"); fzl_an_res_t entry_res = analyze_common(analyzer, block_node->list.entries[i]); if (entry_res.error) error = true; if (block_node->list.entries[i]->type == FZL_NODETYPE_RETURN) has_return = true; } fzl_an_ctx_t *fnctx = analyzer->ctx; while (fnctx != NULL) { if (fnctx && fnctx->type == FZL_AN_CTX_TYPE_FUNCTION) break; fnctx = fnctx->parent; } if (fnctx && fnctx->type == FZL_AN_CTX_TYPE_FUNCTION) { fzl_type_t rettype = an_toktotype(fnctx->fn->fn.type); char *classname = NULL; char *rettype_str = an_typetostr(rettype, classname); if (rettype == FZL_TYPE_OBJECT) classname = (char *)fnctx->fn->fn.type->value; if (rettype != FZL_TYPE_NULL) { if (!has_return || block_node->list.entry_count < 1) { snprintf(an_problem, sizeof(an_problem), "'return <%s>' is expected in the function with non-null " "return type", rettype_str); an_push_error(analyzer, block_node->token, an_problem); return (fzl_an_res_t){.error = true}; } fzl_node_t *last_node = block_node->list.entries[block_node->list.entry_count - 1]; if (last_node->type != FZL_NODETYPE_RETURN) { // NOTE: replace with ghost walker to check if all branch return an // expected value type snprintf(an_problem, sizeof(an_problem), "expected last statement in block to be 'return <%s>'", rettype_str); an_push_error(analyzer, last_node->token, an_problem); return (fzl_an_res_t){.error = true}; } } } an_fin_ctx(analyzer); return (fzl_an_res_t){.error = error, .type = FZL_TYPE_NULL}; }