Подтвердить что ты не робот

Существуют ли Lisp собственные компиляторы кода?

Существуют ли собственные компиляторы кода для Lisp? В какой степени он даже может быть скомпилирован, со всей его динамической природой, сборкой мусора, макросами и чем еще?

4b9b3361

Ответ 1

Многие компиляторы Lisp скомпилируются с "родным" кодом. "Родной" означает здесь "машинный код" (x86 в 32-битном или 64-битном режиме, PowerPC, SPARC,...).

Другие вопросы:

  • могут компиляторы 'non-native code' генерируют исполняемые файлы одного файла? → Да.

  • Компиляторы 'native code' генерируют однофайловые исполняемые файлы? → Да.

  • как "native" является "родным"? → Lisp система в большинстве случаев имеет собственную структуру структуры внутренней структуры (CLOS-классы), собственную обработку ошибок ( "условия" ), собственное управление памятью (сбор мусора), свои собственные библиотеки,...

  • может Lisp работать без GC? → Обычно нет. Есть исключения.

  • Как насчет размера приложения? → По умолчанию простые способы генерации приложения Lisp часто приводят к большим исполняемым файлам. Исполняемые файлы включают в себя весь Lisp, включая его библиотеку, имена всех символов, информацию о списках аргументов для функций, компилятор, отладчик, информацию о местоположении исходного кода и т.д. Некоторые компиляторы генерируют также довольно большой код (пример SBCL).

  • Есть ли способы уменьшить размеры приложений? → Это зависит от системы Lisp. Коммерческие Lisp системы, такие как LispWorks и Allegro CL. Для доставки приложений они могут удалить неиспользуемый код, удалить информацию об отладке, удалить части Lisp (библиотеки, компилятор,...) и многое другое.

  • Общие системы Lisp генерируют небольшие исполняемые файлы. Я имею в виду очень маленький. → Не совсем. Исполняемые файлы являются либо большими (CCL), либо очень большими (SBCL). Некоторые общие системы Lisp могут генерировать исполняемые файлы среднего размера. Но никто не может генерировать небольшие исполняемые файлы.

  • действительно ли невозможно генерировать действительно маленькие исполняемые файлы? → Несколько лет назад были написаны компиляторы, которые генерируют относительно компактный код C без больших библиотек. Но эти компиляторы не поддерживаются.

  • Существуют ли другие способы сокращения исполняемых файлов? → Если вы хотите запустить более одного приложения Lisp, имеет смысл повторно использовать среду выполнения, компилятор, библиотеки в одной или нескольких общих библиотеках. Таким образом, код для доставки будет меньше, когда среда выполнения уже установлена ​​как общая библиотека (или аналогичная).

  • Как узнать, что я использую Lisp в качестве доставки приложения? → прочитайте руководство и спросите других пользователей.

  • в порядке, поэтому большинство обычных систем Lisp не могут генерировать крошечные приложения. Существуют ли другие диалекты Lisp, которые могут создавать меньшие исполняемые файлы. → Да, некоторые компиляторы Схемы могут.

  • как Common Lisp обрабатывает ошибки времени выполнения? → зависит от способа создания приложения. По умолчанию вы получаете отладчик Lisp (если только вы его не удалили). Но вы можете использовать свои собственные процедуры обработки ошибок в своем приложении и можете предотвратить появление отладчика.

  • Каковы общие достоинства Lisp, когда генерация действительно небольших исполняемых файлов не одна? → вы можете включить REPL для взаимодействия с приложением, вы можете использовать включенный компилятор для компиляции нового (или измененного кода) во время выполнения, вы можете использовать загрузчик FASL (скомпилированный Lisp) для дополнительного нативного кода LOAD во время выполнения (думаю, плагины, исправления, расширения,...), возможна сложная обработка ошибок, включая восстановление ошибок,...

  • но Lisp является динамическим? → Да, динамический означает, что во время работы он может многое изменить. Например, в Common Lisp вы можете изменить CLOS-класс во время выполнения, а экземпляры класса будут применены к изменениям. Но различные системы Lisp имеют разные способы удаления некоторых динамических функций. Структуры менее динамичны, чем классы CLOS. Вы можете объявлять типы и компилировать с различными настройками оптимизации (скорость, безопасность, отладка,...). Вы можете выполнять встроенные функции. И еще.

Простым способом просмотра скомпилированного кода для функций является использование функции Common Lisp DISASSEMBLE. Пример в Clozure CL на Mac x86-64

? (defun foo (x y) (if (= x y) (sin x) (* y (cos x))))
FOO
? (disassemble 'foo)
L0
  [0]     (leaq (@ (:^ L0) (% rip)) (% fn))
  [7]     (cmpl ($ 16) (% nargs))
  [10]    (jne L209)
  [16]    (pushq (% rbp))
  [17]    (movq (% rsp) (% rbp))

...

  [172]   (pushq (@ 77752))
  [179]   (jmpq (@ 10 (% temp0)))
L189
  [189]   (leaq (@ (:^ L0) (% rip)) (% fn))
  [196]   (jmpq (@ .SPNVALRET))
L209
  [209]   (uuo-error-wrong-number-of-args)
NIL

Выход DISASSEMBLE, очевидно, зависит от архитектуры процессора, ОС, используемого компилятора Lisp и текущих настроек оптимизации.

Ответ 2

Там много компиляторов Lisp, которые компилируются в собственный код. CMUCL, SBCL, ClozureCL известны среди компиляторов с открытым исходным кодом Lisp.

Сбор мусора не является препятствием для компиляции в собственный код. Кроме того, в некоторых случаях Lisp может использовать распределение стека, которое не требует GC и может значительно повысить производительность (с использованием объявления динамической степени, по крайней мере, SBCL поддерживает это).

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

Таким образом, компилятор более сложный, чем некоторые более простые языки (например, C), но сложность управляема (см. Дизайн CMU Common Lisp).

Динамический характер Common Lisp является управляемым и предназначен для эффективного компиляции. В отличие от некоторых других динамических языков (например, Python) динамизм ограничен (например, вы не можете использовать текущую лексическую среду во время выполнения), что дает компиляторам некоторую свободу для оптимизации.

Ответ 4

Вы ставите. Chez Scheme (коммерческий компилятор) является одним из лучших. Gambit и Larceny - это компиляторы исследований, которые также генерируют собственный код.

Ответ 5

Не забывайте Chicken Scheme.

Ответ 6

Да. См. http://en.wikipedia.org/wiki/Common_Lisp. Он упоминает, что Steel Bank Common Lisp (довольно популярная реализация) компилирует все по умолчанию по умолчанию. Тот факт, что сборки мусора и их использование не является препятствием для собственного кода. Это просто означает, что требуется какая-то среда выполнения. Но что? Даже C имеет время выполнения.