Как бы я реализовал что-то похожее на директиву компилятора Objective-C @encode() в ANSI C?

StackOverflow https://stackoverflow.com/questions/2255637

Вопрос

Директива @encode возвращает const char *, который является дескриптором закодированного типа различных элементов переданного типа данных.Следующий пример:

struct test
{ int ti ;
  char tc ;
} ;

printf( "%s", @encode(struct test) ) ;
// returns "{test=ic}"

Я мог видеть использование sizeof() для определения примитивных типов - и если бы это был полноценный объект, я мог бы использовать методы класса для самоанализа.

Однако, как это определяет каждый элемент непрозрачной структуры?

Это было полезно?

Решение

Ответ @Lothars может быть "циничным", но, к сожалению, он довольно близок к истине.Для того, чтобы реализовать что-то вроде @encode(), вам нужен полноценный синтаксический анализатор, чтобы извлечь информацию о типе.Ну, по крайней мере, для чего угодно, кроме "тривиального". @encode() заявления (т.е., @encode(char *)).Современные компиляторы обычно имеют либо два , либо три основных компонента:

  • Передний конец.
  • Промежуточный конец (для некоторых компиляторов).
  • Задняя часть.

Интерфейс должен анализировать весь исходный код и в основном преобразовывать текст исходного кода во внутреннюю форму, "пригодную для машинного использования".

Серверная часть преобразует внутреннюю форму, "пригодную для машинного использования", в исполняемый код.

Компиляторы, которые имеют "промежуточный конец", обычно делают это из-за некоторой необходимости:они поддерживают несколько "интерфейсов", возможно, состоящих из совершенно разных языков.Другая причина заключается в упрощении оптимизации:все этапы оптимизации работают с одним и тем же промежуточным представлением.В gcc compiler suite - это пример "трехэтапного" компилятора. llvm можно было бы считать компилятором этапа "промежуточный и серверный":"Виртуальная машина низкого уровня" является промежуточным представлением, и вся оптимизация происходит в этой форме. llvm также возможность сохранять его в этом промежуточном представлении вплоть до последней секунды - это позволяет "оптимизировать время соединения".В clang компилятор на самом деле является "внешним интерфейсом", который (эффективно) выводит llvm промежуточное представление.

Итак, если вы хотите добавить @encode() функциональность для "существующего" компилятора, вам, вероятно, пришлось бы делать это как "компилятор / препроцессор от источника к источнику".Именно так были написаны оригинальные компиляторы Objective-C и C ++ - они анализировали исходный текст и преобразовывали его в "обычный C", который затем передавался в стандартный компилятор C.Есть несколько способов сделать это:

Сверни свой собственный

  • Использование yacc и lex чтобы собрать анализатор ANSI-C.Вам понадобится грамматика- Грамматика ANSI C (Yacc) это хорошее начало.На самом деле, чтобы внести ясность, когда я говорю yacc, Я действительно имею в виду бизон и flex.А также, в общих чертах, другие различные yacc и lex как инструменты на основе C: лимонный, анализатор dparser, и т.д...
  • Использование perl с Yapp или ЭЙапп, которые являются псевдо-yacc клоны в perl.Вероятно, лучше для быстрого прототипирования идеи по сравнению с C-based yacc и lex- это perl в конце концов:Регулярные выражения, ассоциативные массивы, отсутствие управления памятью и т.д.
  • Создайте свой анализатор с помощью Antlr ( Антлр ).У меня нет никакого опыта работы с этой цепочкой инструментов, но это еще один инструмент "compiler-компилятор", который (кажется) больше ориентирован на разработчиков Java.По-видимому, существуют свободно доступные грамматики C и Objective-C.

Взломайте другой инструмент

Примечание: У меня нет личного опыта использования любого из этих инструментов для выполнения чего-либо вроде добавления @encode(), но я подозреваю, что они оказали бы большую помощь.

  • СИЛ - Нет личного опыта работы с этим инструментом, но предназначен для разбора исходного кода C, а затем "выполнения работы" с ним.Из того, что я могу почерпнуть из документов, этот инструмент должен позволить вам извлечь необходимую вам информацию о типе.
  • Разреженный - Стоит посмотреть, но не уверен.
  • лязг - Не использовал его для этой цели, но предположительно одной из целей было сделать его "легко взламываемым" именно для такого рода вещей.В частности (и опять же, никакого личного опыта) в выполнении "тяжелой работы" по всему синтаксическому анализу, позволяющей вам сосредоточиться на "интересной" части, которая в данном случае заключалась бы в извлечении информации о типе, зависящей от контекста и синтаксиса, а затем преобразовании ее в обычную строку C .
  • Плагины gcc - Плагины представляют собой функцию gcc 4.5 (которая является текущей альфа / бета-версией компилятора) и "могут" позволить вам легко подключиться к компилятору для извлечения необходимой вам информации о типе.Понятия не имею, допускает ли архитектура плагина такого рода вещи.

Прочее

  • Coccinelle - Недавно добавила это в закладки, чтобы "посмотреть позже".Это "могло бы" быть в состоянии сделать то, что вы хотите, и "могло бы" быть в состоянии сделать это без особых усилий.
  • МетаК - Этот тоже недавно добавил в закладки.Понятия не имею, насколько это было бы полезно.
  • mygcc - "Мог бы" делать то, что ты хочешь.Это интересная идея, но она не применима непосредственно к тому, чего вы хотите.С веб-страницы:"Mygcc позволяет программистам добавлять свои собственные проверки, которые учитывают синтаксис, поток управления и информацию о потоке данных".

Ссылки.

Правка № 1, бонусные ссылки.

@Лотар делает хороший вывод в своем комментарии.На самом деле я намеревался включить lcc, но, похоже, он потерялся по пути.

  • lcc - В lcc Компилятор языка Си.Это компилятор C, который особенно мал, по крайней мере, с точки зрения размера исходного кода.Это также у него есть книга, который я настоятельно рекомендую.
  • tcc - В tcc Компилятор языка Си.Не совсем так педагогично , как lcc, но определенно все еще стоит посмотреть.
  • пок - В poc Компилятор Objective-C.Это компилятор Objective-C "от источника к источнику".Он анализирует исходный код Objective-C и выдает исходный код C, который затем передает gcc (ну, обычно gcc).Имеет ряд расширений / функций Objective-C, которые недоступны в gcc.Определенно стоит посмотреть.

Другие советы

Вы могли бы реализовать это, сначала внедрив компилятор ANSI C, а затем добавив к нему некоторые специфические для реализации прагмы и функции.

Да, я знаю, что это циничный ответ, и я принимаю отрицательные отзывы.

Одним из способов сделать это было бы написать препроцессор, который считывает исходный код для определений типов, а также заменяет @encode...с соответствующим строковым литералом.

Другой подход, если ваша программа скомпилирована с -g, было бы написать функцию, которая считывает определение типа из отладочной информации программы во время выполнения, или использовать gdb или другая программа, которая прочитает его за вас, а затем переформатирует по вашему желанию.В gdb ptype команда может быть использована для печати определения определенного типа (или, если этого недостаточно, также maint print type, который, несомненно, напечатает гораздо больше информации, чем вы могли бы пожелать).

Если вы используете компилятор, который поддерживает Плагины (например,GCC 4.5), также может быть возможно написать для этого плагин компилятора.Затем ваш плагин мог бы воспользоваться информацией о типе, которую компилятор уже проанализировал.Очевидно, что такой подход был бы очень специфичен для компилятора.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top