?

Log in

No account? Create an account
Haskell to JavaScript compiler - ru_declarative [entries|archive|friends|userinfo]
ru_declarative

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Haskell to JavaScript compiler [Nov. 26th, 2007|11:19 pm]
ru_declarative

ru_declarative

[asviraspossible]

Я вот тут занимался тем, что взял стабильную ветку GHC-6.6.1 и добавил в неё возможность генерировать JavaSсript код, чтоб запускать его в браузере. Т. е. идея в том, чтобы писать на Haskell JavaSсript приложения.

Зачем

Дмитрий Голубовский уже сделал трансляцию YHC Core в JavaSсript[1]. Моя реализация сделана на основе GHC, что позволяет (уже сейчас) использовать high-rank polymorphism, existential types, multi parameter type-classes и всё то, что так часто используется. YHC менее поддерживаемый, и содержит некоторые баги, которые делают его даже не Haskell98 совместимым. Я очень уважаю работу проделанную их коммандой, но всё же. Хотелось бы реального распространения и появления реальных Веб-приложений использующих трансляцию Haskell в JavaSсript. Мой исходный код я пока нигде не выкладывал.

Что хотелось бы

Найти человека, который помог бы с хостингом и с разработкой. Или просто готового обменяться идеями. Если кого-то интересует эта тема, свяжитесь со мной по почте.


далее...


Что сделано

  1. Сам транслятор, т. е. берём модифицированный GHC и говорим:

    ghc -fjavasсript -c Test.hs

    На выходе получаем Test.o.js

    Вставляем его в html страничку (<script src="Test.o.js"></script>), запускаем FireFox и видим результат работы программы.

  2. Немного рантайма. Т. е. необходимые функции для работы кода. Сейчас транслятор честно использует модель STG машины, работают апдейты и всё такое. И получаймый код достаточно оптимизированно выглядит.

  3. Ещё немного рантайма. Написано определение монады и реализована функция вывода символа на экран (реализована, как document.write (c) в JavaSсript).

Что необходимо сделать

  1. Нормальный рантайм. Почти что самое главное — это функции конвертации из Haskell-строк в JavaSсript-строки. Типа unpackJSString и packJSString.

  2. Функции для выполнения произвольного JavaSсript кода (внутри JSIO) монады типа

    runJS $ "document.write (\"Hello, " ++ name ++ "
    \n\");"

    должно быть как-то так:

    runJS s = packJSString s >>= jsEval

    jsEvаl должен транслироваться в evаl яваскрипта.

  3. Нормальные ключи в GHC. Сейчас сделан -fjavasсript, но при этом если дописать скажем -O2, то GHC генерирует нейтив код, вместо javasсript. Неясно работает ли это с -make и проверкой в GHC о необходимости компиляции в зависимости от даты модификации файлов. По идее в этом разбирается Simon Peyton Jones, который готов ответить на вопросы в glasgow-haskell-users at haskell dot org списке.

  4. Включение в текущее дерево GHC, опять же к Саймону.

  5. Рефакторинг. Во-первых, возможность добавить всяческую отладочную информацию в результирующий JavaSсript-код, т. е. нужно засунуть транслятор внутрь монады, откуда можно читать ключи коммандной строки. Во-вторых, генерация не самого текста на JavaSсript, а абстрактного синтаксиса JavaSсript, для которого написать или стащить pretty-printer.

  6. Сейчас результирующий javasсript-код использует трамполининг на стеке, чтоб эмулировать хвостовые вызовы. Это не единственный вариант, можно ещё генерировать код в CPS-стиле, тогда можно делать гигантские прыжки на стеке, что, вроде бы, более эффективно. В результате желательно реализовать в трансляторе и то и то.

  7. Оптимизация результирующего кода: убрать обработку неиспользуемых переменных, строить таблицу известных функций, которые можно вызывать напрямую и т. п.

  8. Документация

Более далёкие перспективы:

  1. Линкер. Сейчас в качестве компоновщика выступает человек, т. е. я. Смотрим на отсутствие какой функции ругается FireFox и добавляем ещё один <script src="module.o.js"> в HTML-файл. Нужна какая-то система, в том числе по удалению неиспользуемых функций.

  2. JSIO библиотека. То есть чтение свойств DOM объектов и модификация этих свойств. Решается использованием функции, типа runJS.

  3. Библиотека графических элементов, чтоб можно было строить GUI приложения в браузере. Что-то типа gtk2hs и Google Web Toolkit. Возможно стоит посмотреть на более функциональные модели...

  4. GHC использует сырые (безкоробочные, unboxed) значения. В яваскрипте эта его возможность не нужна и даже вредна, так как там все значения boxed. И если модифицировать прототип у яваскриптового Number, то он будет веcти себя как такое же Closure, как и остальные значения Haskell'а, но при этом его можно будет складывать и умножать. Это тоже к оптимизации...


[1]. http://haskell.org/haskellwiki/Yhc/Javascript

linkReply

Comments:
[User Picture]From: golosptic
2007-11-26 09:14 pm (UTC)
Хм. С разработкой не помогу, хостинг готов обсудить.
А что от него будет надо?
(Reply) (Thread)
[User Picture]From: asviraspossible
2007-11-26 09:38 pm (UTC)
Хотелось бы код как-нибудь выложить, чтоб его листать можно было из
браузера. Может быть darcs сервер и научить меня им пользоваться :) А
так, Вики, больше наверно ничего не надо. Просто сейчас тоже дел
как-то много. Хотелось бы поскорее сделать доступным то что сделано.
Ещё интересно мнение о языке на котором писать документацию, я бы
предложил английский, не смотря на моё несовершенство владения этим
языком.
(Reply) (Parent) (Thread)
[User Picture]From: golosptic
2007-11-26 09:59 pm (UTC)
Darcs у меня не стоит (и не пробовал), хотя можно и подумать
А Вики несколько штук торчит.
Есть, например, вот такое

Можно, впрочем и отдельную вику поднять, хоть и не в один день.

Что касается языка документации - фиг его знает, не исключено, что имеет смысл делать параллельно русскую и английскую версии.
(Reply) (Parent) (Thread)
[User Picture]From: dtim
2007-11-26 09:19 pm (UTC)
Написал в почту.
(Reply) (Thread)
[User Picture]From: lisper
2007-11-26 09:32 pm (UTC)
А чем http://www.flapjax-lang.org/ не угодил ?
(Reply) (Thread)
[User Picture]From: asviraspossible
2007-11-26 09:43 pm (UTC)
Вы делаете неверные выводы
(Reply) (Parent) (Thread)
From: rssh
2007-11-26 09:57 pm (UTC)
Прикольно
Скажете как групу и вики заведете (я бы googler хостинг рекомендовал, он из халявных самый быстрый)
(Reply) (Thread)
[User Picture]From: asviraspossible
2007-11-26 10:31 pm (UTC)
Что за гуглер хостинг?
(Reply) (Parent) (Thread)
[User Picture]From: rssh
2007-11-26 11:07 pm (UTC)
Ой, это я описался
Имелост в виду http://code.google.com/hosting/
(Reply) (Parent) (Thread)
[User Picture]From: p1r4nh4
2007-11-27 10:53 am (UTC)
Там только галимый сабвершен.
(Reply) (Parent) (Thread)
From: rssh
2007-11-27 11:00 am (UTC)
Wiki и багтракинг есть ..... - а, вы о том что настоящим пацанам svn в западло использовать (?) -- тогда флаг вам в руки.
(Reply) (Parent) (Thread)
[User Picture]From: p1r4nh4
2007-11-27 11:34 am (UTC)
Взападло - не взападло, а централизованная тормозная штука мне не всегда удобна.
(Reply) (Parent) (Thread)
[User Picture]From: zelych
2007-11-27 04:00 pm (UTC)
А вот кто бы рассказал как в нецентрализованном darcs'e дать возможность авторизованным пользователям обновлять главный репозитарий (типа pull). Только не через жоп почту.
(Reply) (Parent) (Thread)
From: (Anonymous)
2007-11-27 05:45 pm (UTC)
darcs push через ssh
(Reply) (Parent) (Thread)
[User Picture]From: zelych
2007-11-27 05:53 pm (UTC)
тоже некошерно, после svn и mercurial и git выглядит совсем как каменный век
(Reply) (Parent) (Thread)
From: (Anonymous)
2007-11-27 05:54 pm (UTC)
почему же, это уникс-вей в действии :-)
(Reply) (Parent) (Thread)
[User Picture]From: p1r4nh4
2007-11-28 08:17 am (UTC)
Я в дарксе не силён. Могу рассказать про меркуриал.
(Reply) (Parent) (Thread)
[User Picture]From: zelych
2007-11-28 08:20 am (UTC)
про меркуриал я знаю, очень приятная штука (не в пример дарксу), хотя и написана на идеологически неверном языке
(Reply) (Parent) (Thread)
[User Picture]From: p1r4nh4
2007-11-28 08:22 am (UTC)
Пока он мой любимый. :P А про даркс... медленный он, по сравнению с hg. :-(
(Reply) (Parent) (Thread)
[User Picture]From: zelych
2007-11-28 08:26 am (UTC)
в дарксе хорошо только то, что он на хаскелле написан и под ним есть формальная теория...
(хотя первое не особо спасает, там в коде такая помойка)
(Reply) (Parent) (Thread)
[User Picture]From: p1r4nh4
2007-11-28 08:44 am (UTC)
Угу... Но мне он в любом случае удобнее, чем свн. Хотя фигня, я юзаю hg и не напрягаюсь по поводу альтернатив особо (хотя иногда на bazaar-ng поглядываю, он за последнее время подразогнался).
(Reply) (Parent) (Thread)
From: vag_vagoff
2007-11-28 02:08 pm (UTC)
HTTP PUT cgi script
(Reply) (Parent) (Thread)
[User Picture]From: zelych
2007-11-28 02:51 pm (UTC)
а можно попродробнее? пусть на сервере я скрипт напишу, а у себя на машине я что запускать буду чтобы патчи на сервер отправить?
(Reply) (Parent) (Thread)
From: (Anonymous)
2007-11-27 01:21 pm (UTC)
Чтобы такой экзотический бакенд включили в ghc -- надо очень постараться. Разве не лучше было бы сделать standalone транслятор из ghc core в js?
(Reply) (Thread)
[User Picture]From: asviraspossible
2007-11-27 01:35 pm (UTC)
Во-первых, по-моему вы преувеличиваете это в действительности не очень сложно. Во-вторых в коде GHC и так уже есть транслятор в Java, не знаю что там с рантаймом. Но там всё довольно хорошо сделано, глядя на код. И Хаскелл-типы транслируются в Java-class'ы. А каждая функция транслируется в Java-объект. В-третьих, очень хотелось использовать STG-код, а не Core.
(Reply) (Parent) (Thread)
From: (Anonymous)
2007-11-27 05:44 pm (UTC)
Действительно, есть -- пожалуй, преувеличиваю. От души желаю вам удачи, сам бы помог с радостью, было бы сейчас время.
(Reply) (Parent) (Thread)
From: _san
2007-11-30 10:22 am (UTC)

Про линкер и удаление неиспользуемого кода.

Вы используете, насколько я понял, рукописный javascript в качестве runtime, и подключаете это в html руками. Возможен альтернативный вариант, примененный в GWT (Google Web Toolkit, java->javascript compiler). Там весь runtime написан на java, а самый низкий уровень на так называемых "native" функциях. Гугл использовал стандартное ключевое слово из java, и придал ему тот же смысл, но в javascript контексте.

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

Я про хаскель только начинаю, поэтому могу лишь предположить, что удобно это (написать нативный js) будет сделать не в самих функциях, а в их метаданных (директивах компилятора), таким образом нативный js можно будет использовать и в не-monadic коде.
(Reply) (Thread)