2015-07-13 1 views
2

Немного моего фона: Я разрабатываю некоторые архитектуры процессоров в университете, и теперь я реализую компилятор. Язык будет иметь некоторые специфические характеристики, но в целом он похож на любой другой язык: функции/методы, если они есть, переменные и т. Д.Преимущества и недостатки внедрения include/import/use в компиляторе?

Теперь, что я видел на многих языках, является использование include/импорт/использование конструкций. На моем языке существует только глобальное пространство имен, и я подумал: действительно ли мне нужно реализовать какую-то конструкцию include на моем языке? Не могу ли я просто позволить компилятору быть достаточно умным и выяснить, где находятся определения?

Например, если я компилирую мой код с

./mycompiler file1 file2 file3

И пусть file1 использует что-то определенное в file3. У компилятора достаточно информации, чтобы выяснить, какие потребности file1 были найдены в файле3 (мой компилятор - это компилятор с несколькими проходами). Затем я спрашиваю вас: если мой компилятор достаточно умен, чтобы выяснить, где находятся определения, есть ли какое-то преимущество в явном вводе оператора include/import/use?

ответ

4

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

Однако это крайне нежелательное состояние для программ любого нетривиального размера. Разделение программ на библиотеки и модули является бесценным инструментом для разработки программного обеспечения, и существенной частью этого является выделение этих модулей друг от друга, если программист намеренно и явно не интегрирует их друг с другом. Наличие единого глобального пространства имен уже является помехой в этом идеале, вы не можете назвать вещи в одном модуле независимо от того, как вы (или кто-то еще) назвали вещи в другом модуле.

Кроме того, требуя, чтобы список всех файлов в командной строке был просто глупым. Теперь тот, кто строит программу, должен знать все файлы везде. Это включает в себя все файлы используемых сторонних библиотек и все библиотеки, используемые этими и так далее. Разумеется, этот список обычно будет спрятан в системном файле сборки, но поскольку он транзитивно включает в себя все файлы, составляющие окончательный исполняемый файл, это все еще является бременем обслуживания. Это также не дает вам абсолютно ничего (на самом деле это чистый минус), перечислив эту информацию в исходных файлах.

Что здравые системы модуля (т.е. не #include) сделать это: они выщепляют программу в библиотеки и, кроме того каждый библиотеку в модули или (суб-) пространства имен, а исходного код структура директорий и описывает, в децентрализованная мода, как файлы на диске объединяются в пространства имен, модули, библиотеки. Третья партийная библиотека Джейн Доу описывает свою собственную структуру и имеет собственное пространство имен, поэтому ваш проект может просто указать «Я использую библиотеку foo», и это все.

+0

благодарим вас за ответ! Идея заключалась не в том, чтобы указать, где находятся все файлы, но чтобы компилятор автоматически определял все зависимости. Для программ с нетривиальным размером выполнение будет чем-то вроде ./compiler file1 file2 ... fileN -llib1 -llib2 ... -llibN. Не нужно перечислять все файлы каждой библиотеки, и компилятор должен определить зависимости, непосредственно считывающие код объекта. Сам язык можно рассматривать как модифицированную версию C с поддержкой вывода типа и перегрузки функций. – hdhzero

2

Есть несколько углов, чтобы рассмотреть здесь:

  1. Наличие явного импорта улучшает читаемость. Когда вы читаете исходный код и появляется какая-то неизвестная функция, имея строку вверху, говорящую, что from foo import f дает четкое указание, откуда она взялась.
  2. Наличие нескольких пространств имен снижает риск столкновений. Авторы модулей могут использовать одни и те же имена функций без координации. #include-подобная модульная система не включает это сама по себе.
  3. Компилятор может работать более эффективно, если код разделен на несколько compilation units, поэтому он не перекомпилирует код, который не был изменен. Некоторые исключения: Interprocedural optimization (оптимизация всей программы, оптимизация ссылок), специализированная функция/шаблон (Haskell, C++).
  4. Ваше предложение ./mycompiler file1 file2 file3 напоминает нежелательный способ компиляции программ на основе C, объединяя все файлы исходного кода. Предпочтительной альтернативой в случае C является compile separate object files and link them с использованием somewhat automated Makefiles.
  5. Если вам нужно указать файлы или библиотеки в командной строке, компилятор действительно не «достаточно умен, чтобы выяснить, где находятся определения». Операторы импорта, предполагающие, что модули находятся в файлах, названных одинаково, упрощают их расположение и поиск.
  6. Операции импорта в некоторой степени зависят от исходного кода. Вам нужно меньше пэчворков Makefile и создавать скрипты, но обработка различий между версиями модулей все равно должна идти куда-то, например. в преобразователе ограничений зависимостей в системе пакетов.

C-подобная система шаблонов, из которых #include является одной директивой, безусловно полезна. Если вы считаете, что такие компиляционные директивы/метапрограммирование более интересны для изучения, чем модульные системы, и вы используете минималистические системные языки, рассмотрите вопрос о Nim (ранее Нимрод).

Удачи вам в создании вашего компилятора. :)

+0

./mycompiler file1 file2 file3 делает то, что вы упомянули в 3. Он проверяет, уже ли файл скомпилирован и вместо него использует код объекта. Другими словами, компилятор - это компилятор + make в одном бинарном файле. Я подумал о том, чтобы использовать «./mycompiler main» и позволить автоматически включать все, что было необходимо. Я просто не знал, как создать классный синтаксис для обработки сторонних предварительно скомпилированных библиотек. Я считаю, что это то, что вы имели в виду под 1, 5 и 6. Варианты модулей, приведенные в 6, также заставляли меня задуматься ./mycompiler main vs ./mycompiler file1 file2 -llib1 Спасибо за ваш ответ! – hdhzero

 Смежные вопросы

  • Нет связанных вопросов^_^