Какой самый простой способ создать компилятор F#, который работает на JVM и генерирует Java-байт-код?
Текущий компилятор F# написан на F#, имеет открытый исходный код и работает на.Net и Mono, что позволяет ему работать на многих платформах, включая Windows, Mac и Linux. Механизм кодовых цитат F# использовался для компиляции F# в JavaScript в таких проектах, как WebSharper, Pit и FunScript. Также, кажется, есть некоторый интерес к запуску кода F# на JVM.
Я считаю, что версия компилятора OCaml использовалась для начальной загрузки компилятора F#.
Если бы кто-то хотел создать компилятор F#, который работает на JVM, было бы проще:
- Изменить существующий компилятор F#, чтобы он испускал байт-код Java, а затем скомпилировать с ним компилятор F#?
- Использовать основанный на JVM ML-компилятор, такой как Yeti, чтобы загрузить минимальный F# -компилятор на JVM?
- Переписать F# компилятор с нуля на Java, поскольку проект fjord, кажется, пытается?
- Что-то другое?
6 ответов
Другой вариант, который, вероятно, следует рассмотреть, - преобразовать байтовый код.NET CLR в байтовый код JVM, как это делает http://www.ikvm.net/ с байтовыми кодами JVM > CLR. Хотя этот подход был рассмотрен и отклонен владельцем фьорда.
Получите взнос сверху с опцией 1), и у команды разработчиков F# есть подключаемые бэкэнды, которые теоретически могут издавать звуки байт-кода Java, как если бы это было наиболее удачным решением.
Но если вы посмотрите на другие языки, которые были перенесены на разные платформы, это случается редко. Большую часть времени это было переписано с нуля. Но это также, вероятно, из-за того, что исходная языковая команда не заинтересована в поддержке самих альтернативных платформ и что первоначальная реализация хоста, возможно, не смогла поддерживать несколько бэкэндов, и это уже слишком медленно, чтобы это было возможным вариантом для начала,
Моя догадка - это сочетание переписывания с нуля и возможности сделать как можно больше совместного использования кода и автоматизации из исходной реализации. Например, если бы тестовые наборы могли быть повторно использованы для обеих реализаций, это бы сняло большую нагрузку с порта JVM и проделало бы долгий путь в обеспечении языковой четности.
Если бы мне действительно нужно было это сделать, я бы, вероятно, начал с подхода № 1 - добавить бэкэнд JVM в существующий компилятор. Но я бы также попытался спорить о другой целевой ВМ.
Цитаты не очень актуальны - как автор WebSharper, я могу заверить вас, что, хотя цитаты могут дать вам хороший F#-подобный язык для программирования, они ограничительны и не оптимизированы. Я предполагаю, что для потенциальных пользователей JVM F# планка будет намного выше - полная языковая совместимость и сопоставимая производительность. Это очень сложно.
Взять, например, обратные вызовы. В WebSharper мы применяем эвристику для оптимизации некоторых локальных хвостовых вызовов к циклам в JavaScript, но этого недостаточно - в целом вы не можете полагаться на TCO, как вы это делаете в общих библиотеках F#. Это нормально для WebSharper, так как наши пользователи не ожидают полного F#, но не подходят для порта JVM F#. Я полагаю, что большинство реализаций JVM не используют TCO, поэтому его придется реализовывать с некоторой косвенностью, что приводит к снижению производительности.
Подход к повторной компиляции байт-кода, упомянутый @mythz, звучит очень привлекательно, поскольку он позволяет не только переносить F#- в идеале он позволяет переносить больше программного обеспечения.NET на JVM. Я довольно много работал с анализом байт-кода.NET во внутреннем проекте WebSharper 3.0 - мы рассматриваем возможность компиляции байт-кода.NET вместо цитат F# в JavaScript. Но здесь есть огромные проблемы:
Большая часть кода в BCL непрозрачна (нативна) - и вы не можете декомпилировать его
Модель дженериков довольно сложна. Я реализовал среду выполнения JavaScript, которая с некоторой точностью и разумной производительностью моделирует родовые классы и методы, создание экземпляров, генерацию типов и базовое отражение. Это было достаточно сложно в динамическом JavaScript с замыканиями и кажется довольно сложным в JVM, но я просто не вижу простого решения.
Типы значений создают значительные сложности в байт-коде. Я еще не разобрался с этим для WebSharper 3.0. Их также нельзя игнорировать, так как они широко используются многими библиотеками, которые вы хотели бы перенести.
Точно так же базовое отражение используется во многих реальных библиотеках.NET - и это кошмар для кросс-компиляции с точки зрения как большого количества нативного кода, так и надлежащей поддержки обобщенных типов и типов значений.
Кроме того, подход с использованием байт-кода не снимает вопроса о том, как реализовать хвостовые вызовы. AFAIK, Scala не реализует обратные вызовы. У них, безусловно, есть талант и средства для этого - тот факт, что они этого не делают, многое говорит мне о том, насколько практично использовать TCO на JVM. Для нашего порта.NET->JavaScript я, вероятно, пойду аналогичным путем - никаких гарантий TCO, если только вы не попросите батут, который будет работать, но будет стоить вам порядка (или двух) производительности.
Существует проект, который компилирует OCaml в JVM, OCaml-Java: он довольно полный и, в частности, может компилировать исходные тексты компилятора OCaml (написанные на OCaml). Я не уверен, какие аспекты языка F# вас интересуют, но если вы в основном хотите получить зрелый строго типизированный функциональный язык для JVM, это может быть хорошим вариантом.
Я подозреваю, что любой подход будет большой работой, но я думаю, что ваше первое предложение - единственное, которое позволит избежать появления множества дополнительных несовместимостей и ошибок. Компилятор довольно сложный, и существует множество угловых ситуаций, связанных с разрешением перегрузки и т. Д. (И в спецификации, возможно, также есть пробелы), поэтому маловероятно, что новая реализация будет иметь последовательно совместимую семантику.
Изменить существующий компилятор F#, чтобы он испускал байт-код Java, а затем скомпилировать с ним компилятор F#? Использовать основанный на JVM ML-компилятор, такой как Yeti, чтобы загрузить минимальный F# -компилятор на JVM?
Портировать компилятор не должно быть так сложно, если он написан на F#.
Я бы, наверное, пошел первым путем, потому что это единственный способ сохранить синхронизацию нового компилятора с компилятором.net F#.
Переписать F# компилятор с нуля на Java, поскольку проект fjord, кажется, пытается?
Это, безусловно, наименее элегантный подход, ИМХО.
Что-то другое?
Когда компилятор будет готов, у вас останется 90% работы.
Например, не зная F#, но я предполагаю, что там легко использовать любые библиотеки.NET. Это означает, что основная проблема заключается в портировании экосистемы.NET.
Я искал что-то в похожих строках, хотя это было больше похоже на F# для переводчика / компилятора Akka. Что касается F# -> JVM, я натолкнулся на два не совсем готовых варианта:
1. F# -> [Fjord][1] -> JVM.
2. F# -> [Funscript][2] -> [Vert.X][3] -> JVM