#include #include #include #include #include #include #include #include #include // Analyze field access fzl_an_res_t analyze_field(fzl_analyzer_t *analyzer, fzl_node_t *field) { if (!analyzer) return (fzl_an_res_t){.error = true}; if (!field || field->type != FZL_NODETYPE_FIELD) { an_push_error(analyzer, NULL, "node is not field access"); return (fzl_an_res_t){.error = true}; } fzl_an_res_t parent = analyze_common(analyzer, field->memb.parent); if (parent.error) return (fzl_an_res_t){.error = true}; if (parent.type != FZL_TYPE_OBJECT || parent.classname == NULL) { snprintf(an_problem, sizeof(an_problem), "access to non-object value (%s)", an_typetostr(parent.type, parent.classname)); an_push_error(analyzer, field->token, an_problem); return (fzl_an_res_t){.error = true}; } char *field_name = field->memb.field->token->value; fzl_sym_t sym; bool sym_found = false; for (ssize_t i = analyzer->symbols_top - 1; i >= 0; i--) { if ((sym_found = fzl_symt_get(analyzer->symbols[i], parent.classname, &sym))) break; } if (!sym_found) { snprintf(an_problem, sizeof(an_problem), "class '%s' not found", parent.classname); an_push_error(analyzer, field->parent->token, an_problem); return (fzl_an_res_t){.error = true}; } fzl_node_t *field_node = NULL; for (size_t i = 0; i < sym.node->class.fields_count; i++) { if (strcmp(sym.node->class.fields[i]->var.identifier->token->value, field_name) == 0) { field_node = sym.node->class.fields[i]; break; } } if (field_node == NULL) { snprintf(an_problem, sizeof(an_problem), "field '%s.%s' does not exists", parent.classname, field_name); an_push_error(analyzer, field->memb.field->token, an_problem); return (fzl_an_res_t){.error = true}; } bool type_found = false; fzl_type_t field_type = an_toktotype(analyzer, field_node->var.type, &type_found); if (!type_found) { snprintf(an_problem, sizeof(an_problem), "symbol '%s' not found", (char *)field_node->var.type->value); an_push_error(analyzer, field_node->var.type, an_problem); return (fzl_an_res_t){.error = true}; } char *classname = NULL; if (field_type == FZL_TYPE_OBJECT) classname = field_node->var.type->value; return (fzl_an_res_t){ .error = false, .type = field_type, .classname = classname}; }