Design: Поддержка Prolog и Haskell

Созданный на 30 нояб. 2015  ·  9Комментарии  ·  Источник: WebAssembly/design

Выделите из обсуждения в https://github.com/WebAssembly/design/issues/483 :

Я хотел бы, чтобы были приложены некоторые усилия, чтобы сопоставить эти варианты использования с существующей моделью, а затем оценить, что остается неразрешимым, а что остается неэффективным. Вариант использования нескольких сайтов возврата может относиться к поддержке операции catch или обработки исключений, но не уверен.

30.11.2015 13:45 Фрэнк МакКейб написал:

И Prolog, и Haskell бросают вызов текущему дизайну. В некоторых
у них также есть общее требование: нестандартная оценка
что приводит к необходимости большего контроля над представлением оценки.

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

Вторая особенность - возврат. Что / это / означает, что есть
два разных способа возврата программы: успешно или
безуспешно.

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

В общем, хорошая реализация Prolog требует гораздо более явного
контроль над его оценочным стеком по сравнению с языками Java / C ++.

Haskell - это снова другой случай. Его реализация имеет ряд
функции, которые очень чужды обычным языкам. Во-первых
В этом случае аргументы не оцениваются до входа в функции. В
Эффект от этого состоит в том, что / all / data выглядит как код. Это также означает, что
нормальное отображение массива оценочного стека неэффективно для
Haskell.

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

Во втором случае для вызова функции может быть несколько точек возврата:
один, в котором результат представлен как одно значение, и один или несколько
где результат возврата «откладывается» вместе с компонентами возврата
значение распространяется по нескольким регистрам.

Может ли это быть обработано одним сайтом возврата с использованием нескольких значений (которые должны поддерживаться). Первое значение может быть индексом для отправки в другой диапазон путей возврата?

...

Еще одно замечание: какие структуры необходимы для поддержки Haskell
и Prolog также очень хороши для поддержки так называемого асинхронного
программирование. Таким образом, даже JavaScript и C ++ могут извлечь выгоду из этих
техники.

Но они все равно компилируются в машинный код, а машинный код не имеет специальной поддержки для «асинхронного программирования». Нам нужно знать, может ли AST эффективно поддерживать необходимые примитивные операции.

Самый полезный комментарий

Основной

Я удивлен, что Core не воспитывался относительно Haskell.

Другая цель

Наша цель должна заключаться не в компиляции _Haskell_ в WebAssembly, а в компиляции _Core_ в WebAssembly. Компилятор Haskell GHC уже компилирует Haskell в Core, который меньше по размеру и с ним проще работать, но при этом переносимый. Haskell уже скомпилирован через Core для сборки (с использованием GHC) и байт-кода JVM , поэтому я не понимаю, почему мы не могли сделать что-то подобное для WebAssembly.

GHC делает еще больше

Мы могли бы даже пойти дальше и перехватить GHC позже при компиляции. Например, GHC уже компилирует Core в немного более простую G-машину Spineless Tagless . Затем он преобразует код STG в диалект C-- , после чего даже вызовы функций были удалены. См. GHC § Архитектура в Википедии для целостного объяснения.

Просто сделай это возможным

Конечно, команде WebAssembly необходимо принять во внимание только дизайн системы компиляции Haskell. Кто-то другой может написать компилятор ; нам просто нужно убедиться, что WebAssembly является подходящей целью для такого компилятора, оставаясь при этом относительно небольшим и эффективным. По всей видимости, это уже так, учитывая, сколько работы GHC уже делает для компиляции Haskell на языки более низкого уровня.

Все 9 Комментарий

Вспомогательный Пролог

  1. Функция может быть «возвращена» более одного раза. Это немного похоже на схему call / cc; но нынешняя фиксация на функции как на единице оценки этим нарушается. Стек Пролога значительно богаче, чем стек оценки в большинстве языков, чтобы поддерживать это. Обратите внимание, что, в отличие от call / cc, продолжение в Prolog не может быть восстановлено.
  2. Prolog очень нуждается в разыменовании переменных-переменных. Ссылка на память может иметь не фактическое значение, а указатель на фактическое значение. В некоторых системах на это приходится 30-40% всех циклов ЦП в приложении Prolog.
  3. Обычные алгоритмы сборки мусора на основе полупространства плохо работают с Prolog, потому что эффективное отслеживание с возвратом зависит от знания порядка распределения.

В Прологе это нормально, когда сборщик мусора также собирает стек. Оператор cut в Прологе приводит к появлению записей в стеке мусора.

Поддержка Haskell
Примечание: я не эксперт в этом.

  1. Множественные точки возврата могут быть аппроксимированы возвратом дозорного и ветвления; но со значительными затратами на производительность. Такая система не могла утверждать, что изначально поддерживает Haskell.
  2. Рекурсия хвоста. От хвостового вызова не требуется делать предположения о том, что хвостовой вызов имеет такое же количество параметров и т. Д., Что и родительский вызов. Во многих случаях на функциональных языках это будет выглядеть иначе.
  3. Стек нелинейных оценок. Обычный режим отложенного вычисления Haskell очень затрудняет реализацию в стеке. Насколько мне известно, компилятор Haskell пытается сопоставить оценку со стеком, но обычно терпит неудачу и в итоге получает стек, выделенный кучей.

29 ноября 2015 г. в 20:46 Фрэнк МакКейб [email protected] написал:

Вспомогательный Пролог

Функция может быть «возвращена» более одного раза. Это немного похоже на схему call / cc; но нынешняя фиксация на функции как на единице оценки этим нарушается. Стек Пролога значительно богаче, чем стек оценки в большинстве языков, чтобы поддерживать это. Обратите внимание, что, в отличие от call / cc, продолжение в Prolog не может быть восстановлено.
Какая функция низкого уровня вам нужна? Это несколько точек входа в функции?

Обратите внимание, что ничто не мешает реализации пролога в Интернете для распределения в куче структур данных, подобных стеку, и использования их в качестве стека высокого уровня. Если бы реализация пролога сделала это при генерации кода C, насколько она была бы хуже - с точки зрения общей производительности тестов - чем реализация, нацеленная на машинный код и делающая что-то более умное?

Prolog очень нуждается в разыменовании переменных-переменных. Ссылка на память может иметь не фактическое значение, а указатель на фактическое значение. В некоторых системах на это приходится 30-40% всех циклов ЦП в приложении Prolog.
Чем желаемый машинный код отличается от того, который генерировал бы компилятор C, если бы вы выразили это с помощью C?
Обычные алгоритмы сборки мусора на основе полупространства плохо работают с Prolog, потому что эффективное отслеживание с возвратом зависит от знания порядка распределения.

В Прологе это нормально, когда сборщик мусора также собирает стек. Оператор cut в Прологе приводит к появлению записей в стеке мусора.

Любые функции сборки мусора для wasm должны быть совместимы с семантикой сборки мусора в Интернете. Непонятно, совместимо ли то, что вы описываете.

Ничто не мешает индивидуальной реализации GC с использованием линейной памяти.

Поддержка Haskell
Примечание: я не эксперт в этом.

Множественные точки возврата могут быть аппроксимированы возвратом дозорного и ветвления; но со значительными затратами на производительность. Такая система не могла утверждать, что изначально поддерживает Haskell.
Рекурсия хвоста. От хвостового вызова не требуется делать предположения о том, что хвостовой вызов имеет такое же количество параметров и т. Д., Что и родительский вызов. Во многих случаях на функциональных языках это будет выглядеть иначе.
Стек нелинейных оценок. Обычный режим отложенного вычисления Haskell очень затрудняет реализацию в стеке. Насколько мне известно, компилятор Haskell пытается сопоставить оценку со стеком, но обычно терпит неудачу и в итоге получает стек, выделенный кучей.
-
Ответьте на это письмо напрямую или просмотрите его на GitHub.

Какая функция низкого уровня вам нужна? Это несколько точек входа в функции?

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

Отображение этого на C приводит либо к чрезвычайно объемному коду, либо, что более вероятно, к дополнительному уровню интерпретации. Большинство достойных систем Prolog не компилируются на C.

В некоторых системах на это приходится 30-40% всех циклов ЦП в приложении Prolog.

Чем желаемый машинный код отличается от того, который генерировал бы компилятор C, если бы вы выразили это с помощью C?

Ключевым моментом здесь является то, что вы получите то, что для верификатора будет похоже на нарушение типа. Указатель на значение может быть указателем на указатель на значение или указателем на указатель на указатель на значение; или это может быть просто ценность.

Компиляция через C неизбежно приводит к существенной потере производительности.

Пару мест, где вы говорите, что можно просто выделить кусок линейной памяти и поиграть с ним. Это правда. Но вы не можете одновременно использовать это как предпочтительную стратегию и претендовать на универсальность.

Это может проиллюстрировать крайний пример: вы можете отобразить все программы на C в Haskell. Тогда можно было бы утверждать, что при эффективной реализации Haskell у вас также есть эффективная реализация C и универсальность. Я сомневаюсь, что многие люди согласятся с этим.

С другой стороны, не требуется поддержки Prolog или Haskell. Только не претендуйте на универсальность в этом случае.

Некоторые другие языки, которые также имеют нестандартные модели выполнения, включают SQL, Scheme, Ruby, ...

Ничто не мешает индивидуальной реализации GC с использованием линейной памяти.

Просто хотел отметить, что я думаю, что это будет обычным явлением. Существует слишком много разных моделей GC, ни одна виртуальная машина не может поддерживать их все (другой пример - языки, которым нужны финализаторы GC, которых нет в JS), и это нормально. Остальные могут быть реализованы поверх линейной памяти (+ потоки) со скоростью, близкой к собственной.

Пару мест, где вы говорите, что можно просто выделить кусок линейной памяти и поиграть с ним. Это правда. Но вы не можете одновременно использовать это как предпочтительную стратегию и претендовать на универсальность.

Я не думаю, что мы претендуем на сильную универсальность в этом смысле. Это никогда не было достигнуто и, вероятно, просто невозможно.

Основная цель WebAssembly - действовать как ассемблер для JavaScript? Я думал, что у нас уже есть распространенная реализация JS.

Я также думал, что первоначальной целью была возможность компилировать произвольные программы на C для распространения в браузерах.

Думаю, я немного повысил ставку. Я думаю, что есть потенциал для универсального ассемблера.

Цели WebAssembly в изложены здесь . Первоначальный акцент (MVP) действительно сделан на C / C ++, но это также очень большое намерение «поднять ставку» сверх этого и добавить поддержку многих других типов языков.

Документ FutureFeatures.md представляет собой список некоторых возможных идей (включая полностью общие хвостовые вызовы ), также возможны и другие идеи. Это не исчерпывающий список; приветствуются новые идеи.

Для Haskell хорошей отправной точкой для исследования может быть бэкэнд GHC LLVM. От каких особенностей LLVM это зависит? В чем его слабые стороны?

Закрытие, поскольку не было выявлено ничего достаточно конкретного, и, если обнаружено, кажется более подходящим открыть новые конкретные вопросы.

Основной

Я удивлен, что Core не воспитывался относительно Haskell.

Другая цель

Наша цель должна заключаться не в компиляции _Haskell_ в WebAssembly, а в компиляции _Core_ в WebAssembly. Компилятор Haskell GHC уже компилирует Haskell в Core, который меньше по размеру и с ним проще работать, но при этом переносимый. Haskell уже скомпилирован через Core для сборки (с использованием GHC) и байт-кода JVM , поэтому я не понимаю, почему мы не могли сделать что-то подобное для WebAssembly.

GHC делает еще больше

Мы могли бы даже пойти дальше и перехватить GHC позже при компиляции. Например, GHC уже компилирует Core в немного более простую G-машину Spineless Tagless . Затем он преобразует код STG в диалект C-- , после чего даже вызовы функций были удалены. См. GHC § Архитектура в Википедии для целостного объяснения.

Просто сделай это возможным

Конечно, команде WebAssembly необходимо принять во внимание только дизайн системы компиляции Haskell. Кто-то другой может написать компилятор ; нам просто нужно убедиться, что WebAssembly является подходящей целью для такого компилятора, оставаясь при этом относительно небольшим и эффективным. По всей видимости, это уже так, учитывая, сколько работы GHC уже делает для компиляции Haskell на языки более низкого уровня.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги