Перейти к содержимому
cd /languages
  • Системное ядро
  • Программирование
  • Поддержка AST и символов

C в Maguyva: графы вызовов для системного и встраиваемого кода

Maguyva поддерживает C с AST, символами и графом, чтобы ИИ-агенты отслеживали функции, структуры, include и вызывающих в системном коде, прошивках и библиотеках.

Почему C нужен граф вызовов, а не grep

В C нет классов и модулей, которые упорядочивали бы код. Структура живёт в вызовах функций, заголовках и структурах, а одно и то же имя может встречаться в комментариях, макросах и строковых литералах. Макросы экспорта и аннотаций оборачивают объявления, и инструменты, умеющие разбирать только чистый C, на них спотыкаются. Для агента безопасный первый шаг — граф вызовов.

Maguyva строит этот граф, чтобы агент видел, до чего доходит функция и что доходит до неё, прежде чем предложить изменение.

Что Maguyva извлекает из C

Maguyva охватывает .c и .h. Определения функций извлекаются как символы, а структуры и объединения можно выбрать как определения типов в структурном поиске. Директивы #include становятся связями импорта.

Макросы экспорта и видимости (шаблоны вроде FOO_API, DLLEXPORT или LIBEXPORT) и макросы аннотаций потокобезопасности (например, GUARDED_BY и REQUIRES) маскируются перед разбором, поэтому обёрнутые ими объявления по-прежнему распознаются как объявления. Тела функциональных макросов разбираются, тела объектных макросов — нет.

Граф фиксирует вызовы, include, создание экземпляров через составные литералы, ссылки на типы, чтения и записи, а также поток управления. Около 124 вызовов стандартной библиотеки C (printf, malloc, free, memcpy, strlen и подобные) отфильтровываются из связей, чтобы код проекта был на виду.

Примеры промптов для агентов

  • «Кто вызывает uart_write — напрямую или через другие функции?» (dependency_search incoming)
  • «Какие файлы подключают config.h и какие его структуры используют?» (dependency_search, затем find_symbol)
  • «Объясни, как пакет проходит от прерывания приёма до парсера протокола.» (get_task_context)

Известные ограничения

  • В C нет классов и исключений, поэтому связи наследования, реализации интерфейсов, переопределения, выброса и перехвата помечены как неприменимые.
  • .h входит в списки расширений C, C++ и Objective-C, поэтому заголовки в многоязычных деревьях общие для этих профилей.
  • Вызовы отфильтрованных функций стандартной библиотеки не становятся рёбрами графа. Если нужен каждый malloc или memcpy, используйте text_pattern_search.

Следующие шаги

Подключите репозиторий по быстрому старту, затем изучите матрицу поддержки на странице совместимости. Для кода на C++ в том же дереве прочитайте руководство по C++.

Лучше всего подходит

  • > Команды прошивок, встраиваемых систем и операционных систем, где небольшое изменение общей функции может дойти до аппаратных путей.
  • > Долгоживущие библиотеки на C с публичными заголовками, макросами экспорта и множеством внутренних единиц трансляции.
  • > Ревью с участием агентов, где вопрос звучит так: «кто это вызывает и через какие заголовки?»

Сценарии работы агента

  • > Найти всех вызывающих функцию, прежде чем менять её сигнатуру или обработку ошибок.
  • > Составить карту файлов, подключающих заголовок, и структур, которые они используют.
  • > Проследить запрос от обработчика прерывания или точки входа через функции, до которых он доходит.

Детали движка

  • > Поддержка C охватывает `.c` и `.h`. Определения функций — символы, структуры и объединения — определения типов, а `#include` становится связью импорта.
  • > Макросы экспорта, видимости и аннотаций потокобезопасности маскируются перед разбором, поэтому обёрнутые объявления разбираются. Тела функциональных макросов разбираются, объектных — нет.
  • > Около 124 вызовов стандартной библиотеки, таких как `printf`, `malloc` и `memcpy`, отфильтровываются. Связи наследования, переопределения и исключений помечены как неприменимые.

Полезные точки входа MCP

  • find_symbol

    Используйте с именем функции или структуры, когда нужны определение и все ссылки.

  • dependency_search

    Используйте обход incoming для общей функции перед изменением её сигнатуры или обработки ошибок.

  • get_task_context

    Используйте для промптов вроде «объясни, как пакет проходит от прерывания приёма до парсера протокола».