Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.12.24 05:19
Оценка:
Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.
А есть ли аналог этой библиотеки на тайпскрипте?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хочется странного
От: · Великобритания  
Дата: 15.12.24 08:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

S> Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S> А есть ли аналог этой библиотеки на тайпскрипте?
А у тайпскрипта разве есть байткод? wasm что-ли?
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: Хочется странного
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 15.12.24 09:13
Оценка:
Здравствуйте, ·, Вы писали:

·>А у тайпскрипта разве есть байткод? wasm что-ли?

Я почему-то подумал, что коллега хочет именно Java-байткод на TS.
Под определение странного это вписывается вполне.
Re: Хочется странного
От: Слава  
Дата: 15.12.24 09:58
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S>А есть ли аналог этой библиотеки на тайпскрипте?

Наверное есть на С++, а оттуда уже можно сделать wasm и к нему интерфейс на TS.
Re[2]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.12.24 16:07
Оценка:
Здравствуйте, ·, Вы писали:
·>А у тайпскрипта разве есть байткод? wasm что-ли?
Нет. Байткод нужен джавный. Просто писать компиляторщину на Java — это боль.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Хочется странного
От: · Великобритания  
Дата: 15.12.24 16:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>А у тайпскрипта разве есть байткод? wasm что-ли?

S>Нет. Байткод нужен джавный. Просто писать компиляторщину на Java — это боль.
А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 01:23
Оценка:
Здравствуйте, ·, Вы писали:
·>А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.
Задача — сделать компилятор воображаемого языка.
В JVM — потому, что это проще, чем в натив (и даже в LLVM).
В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода
Вот, кстати, смотрю в сторону kotlin. Похоже, на нём тоже неплохо пишется компилятор. Но для него, я так понял, в качестве IDE можно использовать только IntelliJ, т.к. интеграция с VS Code у него так себе.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Хочется странного
От: amironov79  
Дата: 16.12.24 06:26
Оценка: 82 (1)
Здравствуйте, Sinclair, Вы писали:

S>Задача — сделать компилятор воображаемого языка.

S>В JVM — потому, что это проще, чем в натив (и даже в LLVM).

GraalJs? Ну и "typescript for jvm" находит какие-то проекты, в большинстве случаев архивные.

S>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода

S>Вот, кстати, смотрю в сторону kotlin. Похоже, на нём тоже неплохо пишется компилятор. Но для него, я так понял, в качестве IDE можно использовать только IntelliJ, т.к. интеграция с VS Code у него так себе.

Ну Kotlin с IntelliJ (есть community версия) всяко лучше будет, чем натягивать Ts на Jvm
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 06:57
Оценка:
Здравствуйте, amironov79, Вы писали:

A>GraalJs? Ну и "typescript for jvm" находит какие-то проекты, в большинстве случаев архивные.

Большинство этих проектов — про исполнение typescript в JVM. А мне как раз это не очень надо, typescript пускай себе в node.js работает.

A>Ну Kotlin с IntelliJ (есть community версия)

Ладно, попробуем.
A>всяко лучше будет, чем натягивать Ts на Jvm
Натягивать TS на JVM нужды нет. Всё, что нужно — это порождать .class. Это можно делать из примерно любого языка — С++, Pascal, Java, you name it.
Вопрос только в доступности инструментальных средств.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Хочется странного
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 16.12.24 07:29
Оценка: 82 (1)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, ·, Вы писали:

S>·>А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.
S>Задача — сделать компилятор воображаемого языка.
О! Это какой-то курс по трансляторам?
А можете поделиться — вы планируете чтобы студенты и фронт (анализ) и бэк (генерацию) писали врукопашную?
Я в свое время на такое не решился (но там был курс для заочников — они бы просто не успели вообще всё).

И выбрал вариант:
— используем генератор анализаторов (я брал ANTLR)
— для генерации использовал выход в виде IL-файла

Мне такой вариант понравился тем, что:
— всё наглядно: сразу видно, что получилось
— можно использовать текстовые шаблоны генерации — это актуально если делать DSL, который порождает не сразу байткод, а код на другом языке.
Этот подход очень развит в том же ANTLR, с его глубокой интеграцией в текстовые шаблоны

Я делал по практике пару "методичек". Какраз по ANTLR и немного по IL.
Если вдруг заинтересует, можете посмотреть https://mihailromanov.github.io/docs/tutorials/
Но ... сейчас я бы всё сделал иначе + это всё очень устарело, но вдруг натолкнет на интересные мысли...

S>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода

А если рассмотреть вариант с .Net?
Т.е. фронт на C# (или даже F#!) а для генерации, что-то типа https://www.nuget.org/packages/Fluent.IL

Или есть какие-то ограничения и .Net нельзя ни в коем случае?

P.S. Мне еще в качестве генераторов парсеров очень понравился Irony https://www.nuget.org/packages/Irony

Минимум зависимостей и не нужны специальные инструменты. По сути DSL для описания языка прямо на C#.
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 08:12
Оценка: 20 (1)
Здравствуйте, Михаил Романов, Вы писали:
МР>О! Это какой-то курс по трансляторам?
Да. "Методы трансляции и компиляции".
МР>А можете поделиться — вы планируете чтобы студенты и фронт (анализ) и бэк (генерацию) писали врукопашную?
Нет, пусть они пользуются готовыми инструментами. Но им нужно научиться самим писать грамматики и трансформировать код.
У нас этот курс уже есть, но к нему есть претензии. Основная претензия — чрезмерная воображаемость языков.
Код практики пишется на языке flow9, которым пользуется примерно столько же народу, сколько у нас студентов .
При этом компиляция и верификация пишется для недетерминированного языка, что сильно ломает мозг студентам.
Вот, думаем над тем, чтобы
а) убрать реализацию своей VM — там всё равно VM получается ущербной, и совершенно непохожей на настоящие VM.
б) заменить недетерминированный воображаемый язык на что-то больше похожее на обычные императивные языки
в) использовать в качестве основного языка программирования что-то более промышленно-стандартное, то есть хорошо документированное и стабильно работающее.

МР>- используем генератор анализаторов (я брал ANTLR)

У нас используется PEG. У PEG-грамматик есть ряд преимуществ перед традиционными LL(*), LR(k) и прочимию LALR(1)/LR/IELR(1)/GLR
МР>- для генерации использовал выход в виде IL-файла
Ну, я думал над CIL в качестве целевого языка. Но по ряду причин лучше было бы взять Java. В частности, у меня есть желание научить их сразу генерировать отладочные символы, что даст возможность интерактивной отладки программок на их воображаемом языке. На майкрософтовской стороне забора это требует разбираться с PDB, который вообще ортогонален кодогенерации; а в жаве всё лежит в тех же .class файлах.

МР>- можно использовать текстовые шаблоны генерации — это актуально если делать DSL, который порождает не сразу байткод, а код на другом языке.

Порождать текстовый язык мы их и так будем учить — там одна из задач сводится к генерации системы уравнений для Z3 на его языке SMTLIB.
МР>Этот подход очень развит в том же ANTLR, с его глубокой интеграцией в текстовые шаблоны
МР>Я делал по практике пару "методичек". Какраз по ANTLR и немного по IL.
МР>Если вдруг заинтересует, можете посмотреть https://mihailromanov.github.io/docs/tutorials/
Да, спасибо, очень интересно.
МР>Но ... сейчас я бы всё сделал иначе + это всё очень устарело, но вдруг натолкнет на интересные мысли...

МР>А если рассмотреть вариант с .Net?

МР>Т.е. фронт на C# (или даже F#!) а для генерации, что-то типа https://www.nuget.org/packages/Fluent.IL
Если честно, C# — не лучший язык для таких вещей.
Идеально — строготипизированный язык с автовыводом типов. В частности, это позволяет очень сильно упростить описания грамматик в PEG, потому что не надо выписывать result type для каждого семантического действия.
Из промышленных языков больше всего похож на то, что надо, собственно typescript. Генерация кода — да, в дотнете она сделана сильно более понятно, чем в Java.
Для C# есть библиотека PEG-разбора, но грамматики на ней.... обнять и плакать. На F# не смотрел.
Никакого сравнения с грамматиками Lingo, которая встроена в flow9.
МР>Или есть какие-то ограничения и .Net нельзя ни в коем случае?
Да в целом-то ограничений нет; если бы просматривалась возможность покрыть все аспекты курса, оставаясь в рамках дотнета — то можно было бы наверное и его протащить. Но пока выглядит так, что Java в среднем встретит больше понимания (и органичнее впишется в другие курсы, которые читаются тем же студентам).

МР>P.S. Мне еще в качестве генераторов парсеров очень понравился Irony https://www.nuget.org/packages/Irony

Посмотрим.
МР>Минимум зависимостей и не нужны специальные инструменты. По сути DSL для описания языка прямо на C#.
Документации маловато. Из сэмплов выглядит так, что он генерирует LR парсеры?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Хочется странного
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 16.12.24 09:50
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Код практики пишется на языке flow9, которым пользуется примерно столько же народу, сколько у нас студентов .

Ну да, я впервые услышал https://github.com/area9innovation/flow9
Прикольно, что контрибьютеры в подавляющем большинстве из России или с Украины

S>У нас используется PEG. У PEG-грамматик есть ряд преимуществ перед традиционными LL(*), LR(k) и прочимию LALR(1)/LR/IELR(1)/GLR

У меня тут мало опыта, поэтому ничего сказать не могу. Наверное так и есть.

S>Ну, я думал над CIL в качестве целевого языка. Но по ряду причин лучше было бы взять Java. В частности, у меня есть желание научить их сразу генерировать отладочные символы, что даст возможность интерактивной отладки программок на их воображаемом языке. На майкрософтовской стороне забора это требует разбираться с PDB, который вообще ортогонален кодогенерации; а в жаве всё лежит в тех же .class файлах.

Опять же не разбирался, не могу ничего сказать.
Вроде как есть такие вещи как как ILGenerator.MarkSequencePointCore, но они тянут за собой пространство System.Diagnostics.SymbolStore, так что, похоже, всё не так просто как мне казалось.

S>Если честно, C# — не лучший язык для таких вещей.

S>Идеально — строготипизированный язык с автовыводом типов. В частности, это позволяет очень сильно упростить описания грамматик в PEG, потому что не надо выписывать result type для каждого семантического действия.
S>Из промышленных языков больше всего похож на то, что надо, собственно typescript.
Понятно. Я, увы, забросил этот вопрос весьма давно — хочется вернуться и посмотреть на что-то еще помимо, простых генераторов и как работается с ними в простых императивных языках. Но времени как всегда нет ни на что.

По поводу генерации — я немного ввел вас в заблуждение (хотя, может вы и были в курсе).
В .Net после Framework и вплоть до 9 версии, была недоступна функциональность выгрузки сгенерированной сборки вовне.
В 9 появился PersistedAssemblyBuilder, но всякие обертки над Emit его пока не подхватили.
А если взглянуть на использование его напрямую (на базовом Emit) то, конечно, делается печально https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.

МР>>Минимум зависимостей и не нужны специальные инструменты. По сути DSL для описания языка прямо на C#.

S>Документации маловато. Из сэмплов выглядит так, что он генерирует LR парсеры?
Это правда. Я смотрел на примеры и через утилиту (GrammarExplorer вроде)

По грамматике, вроде как LALR https://www.codeproject.com/Articles/22650/Irony-NET-Compiler-Construction-Kit?msg=2381770

Ну и я подумал, что вас он вряд ли впечатлит — там нормальной типизации узлов разбора не будет из коробки, а значит всё равно в рукопашную резвись с тем, что он там наразбирал...
Re[5]: Хочется странного
От: Pzz Россия https://github.com/alexpevzner
Дата: 16.12.24 11:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Задача — сделать компилятор воображаемого языка.

S>В JVM — потому, что это проще, чем в натив (и даже в LLVM).

А ты в курсе, что есть древний, как UNIX System 7, паттерн делать такие компиляторы, используя Си в качестве промежуточного представления? А потом уже штатным компилятором Си — в нативный код.
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 12:16
Оценка:
Здравствуйте, Pzz, Вы писали:
Pzz>А ты в курсе, что есть древний, как UNIX System 7, паттерн делать такие компиляторы, используя Си в качестве промежуточного представления? А потом уже штатным компилятором Си — в нативный код.
В курсе. А ещё можно их фортрану обучать на перфокартах
Мы-то хотим более-менее современному их обучать. В частности, нет никакого желания тиранить их лексерами — ни рукопашными, ни автопорождёнными.
Ну и с представлениями тоже — никто в здравом уме не будет порождать код для JVM через Си как промежуточный язык.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 12:44
Оценка: 22 (2)
Здравствуйте, Михаил Романов, Вы писали:
МР>Ну да, я впервые услышал https://github.com/area9innovation/flow9
МР>Прикольно, что контрибьютеры в подавляющем большинстве из России или с Украины
Отож.

МР>У меня тут мало опыта, поэтому ничего сказать не могу. Наверное так и есть.

Главное — он безлексерный и unambiguous. Нет никаких конфликтов, которые нужно как-то разрешать.
Плюс — очень естественно обобщается на инкрементальность.

МР>Вроде как есть такие вещи как как ILGenerator.MarkSequencePointCore, но они тянут за собой пространство System.Diagnostics.SymbolStore, так что, похоже, всё не так просто как мне казалось.

Вот и я не разбирался .

МР>В .Net после Framework и вплоть до 9 версии, была недоступна функциональность выгрузки сгенерированной сборки вовне.

Это вообще не проблема. Я когда переезжал с фреймворка на Core, взял https://github.com/Lokad/ILPack и поехал.
МР>В 9 появился PersistedAssemblyBuilder, но всякие обертки над Emit его пока не подхватили.
МР>А если взглянуть на использование его напрямую (на базовом Emit) то, конечно, делается печально https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.

МР>По грамматике, вроде как LALR https://www.codeproject.com/Articles/22650/Irony-NET-Compiler-Construction-Kit?msg=2381770

Спасибо за внятный пример.
Вот по нему уже видно, за что можно не любить все эти тяжеловесные парсер-генераторы.
Для сравнения — полный код PEG-грамматики, которая разбирает арифметические выражения и строит типизированное AST на Lingo:
expr = sum;
sum = mul:head summand*:tail { buildChain(:head, :tail) };
summand = (("+" {Add()}) | ("-" {Sub()})):op mul:s { BinOperand(:op, :s) };
mul = pow:head factor*:tail { buildChain(:head, :tail)};
factor = (("*" {MulOp()}) | ("/" {DivOp()})):op pow:m{ BinOperand(:op, :m) };
pow = atom:base "**" pow:degree { Bin(:base, :degree, Pow()) } | atom;
atom = var | number | "(" expr:e ")" {:e};
var = (letter digit*) $vn { Var($vn) }; 
number = (digit+) $n {Int(s2i($n))};
digit = '0'-'9';
letter = ('a' - 'z' | 'A' - 'Z');

Для того, чтобы это взлетело, нужны описания типов AST на стороне flow9 и однострочная функция для сворачивания левоассоциативных выражений:

Expr ::= Bin, Var, Int;
BinOperand(op: BinOp, right: Expr);
Bin(left: Expr, right: Expr, op:BinOp);
BinOp ::= AddOp, SubOp, MulOp, DivOp, PowOp;
AddOp(); SubOp(); MulOp(); DivOp(); PowOp();


МР>Ну и я подумал, что вас он вряд ли впечатлит — там нормальной типизации узлов разбора не будет из коробки, а значит всё равно в рукопашную резвись с тем, что он там наразбирал...

Именно. Гораздо удобнее работать с типизированным AST.
Как раз автовывод типов этим и прекрасен — ведь любое правило в PEG-грамматике описывается семантическим действием; если тип этого действия известен, то и тип правила известен.
Остаётся правильно вывести тип для правил с альтернативами — и мы получаем то, что нужно.
По идее это должно ездить и на typescript; но пока что я не нашёл идеальной ts-реализации PEG. PEGjs выглядит заброшенным и он всё же JS, а не TS; Ohm неплох (и умеет инкрементальность из коробки), но у них очень странные идеи про то, как привязывать семантические действия к грамматике.
В общем, нету серебряной пули
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хочется странного
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.24 13:52
Оценка: -1 :)
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S>А есть ли аналог этой библиотеки на тайпскрипте?

Пишем кастомный трансформер AST на TypeScript
и солнце б утром не вставало, когда бы не было меня
Re[2]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 14:23
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Пишем кастомный трансформер AST на TypeScript

Спасибо, но это не про то. У меня (пока) нет задачи улучшить компилятор тайпскрипта.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Хочется странного
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.24 14:27
Оценка: -1 :)
Здравствуйте, Sinclair, Вы писали:


S>>Пишем кастомный трансформер AST на TypeScript

S>Спасибо, но это не про то. У меня (пока) нет задачи улучшить компилятор тайпскрипта.

Не там есть пример получения ast.json

Каждый раз, когда мне необходимо проделать что-либо с AST, я первым делом открываю astexplorer.net, а затем начинаю действовать. Этот инструмент позволяет проанализировать AST, созданное различными парсерами, в том числе babel/parser и парсером компилятора TypeScript. С помощью astexplorer.net можно визуализировать структуры данных, с которыми вам предстоит работать, и ознакомиться с типами узлов AST каждого парсера.


Взгляните на пример файла исходных данных и AST, созданное на его основе с помощью babel-parser:



example.ts
import { protos } from 'my_company_protos'

export type User = protos.user.User;


ast.json
{
  "type": "Program",
  "start": 0,
  "end": 80,
  "loc": {
    "start": {
      "line": 1,
      "column": 0
    },
    "end": {
      "line": 3,
      "column": 36
    }
  },
  "comments": [],
  "range": [
    0,
    80
  ],
  "sourceType": "module",
  "body": [
    {
      "type": "ImportDeclaration",
      "start": 0,
      "end": 42,
      "loc": {
        "start": {
          "line": 1,
          "column": 0
        },
        "end": {
          "line": 1,
          "column": 42
        }
      },
... большой файл
и солнце б утром не вставало, когда бы не было меня
Re[4]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 16:38
Оценка:
Здравствуйте, Serginio1, Вы писали:
S> Не там есть пример получения ast.json
Там пример получения AST программы, написанной на typescript.
Предсказуемо, для этого применяется компилятор TS
У нас задача совсем другая — нужно получить AST своего воображаемого языка, а потом сгенерировать для него байткод.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хочется странного
От: GarryIV  
Дата: 17.12.24 12:00
Оценка: 84 (1)
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

Есть еще JEP 466: Class-File API (Second Preview)
WBR, Igor Evgrafov
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.