Это копия, сохраненная 23 июня 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Yupiel - языко-ориентированный язык программирования основанный на механизме перезаписи строк.
Синтаксис
В языке есть только одна конструкция - правило. Вся программа на Юпиель представляет из себя список правил вида:
Type :: Pattern => Replacement
или
Type :: Pattern
Type - терм, обознающий тип выражение.
Pattern - набор символов и нетерменалов.
Нетерминалы обозначаются как |var : Type|, где var - имя переменой (может быть любой последовательностью символов, кроме `|` и ` `.
Replacement - набор символов и нетерминалов вида |var|.
Пример:
Effect :: print |arg : Expr| => console.log(|arg|)
Всякий набор правил Юпиель называется модулем (module).
Текст, подаваемый в модуль, называется источником (source).
Текст, выдаваемый модулем, называется целью (target).
Задача модуля - превратить код из языка Source в код языка Target.
Универсальность и встраемость
Юпиэль - транспилятор. У него нет рантайма, а это значит, что ты можешь писать код (с любым синтаксисом, который ты поделаешь), и запускать его в браузере или на Go-сервере, или... да где угодно. Хоть ардуину программируй.
Твоя говноконтора программирует на говноязыке X? Просто прозрачно превращай свой идеальный язык Y в говноязык X с помощью Yupiel.
Выразительность
Код на Юпиель такой, каким ты хочешь его видеть.
Простота
В Юпиеэль есть только одна вещь - правило.
Простая отладка
Просматривай поэтапно процесс транспиляции.
> имплементация?
Её пока нет. Однако будет создан proof-of-concept транспилятор Yupel.
И да, язык назван в честь одной хентай-манги.
Ты изобрёл макросы.
По-сути, в правила Юпиэль - это макросы, но с произвольным синтаксисом. Правила Юпиель можно рассматривать как правила парсера Эрли, но с дополнительной частью в виде замены. Невероятно просто, однако, почему-то это еще никто не реализовал.
Алсо, макросы во всех языках могут работать только с термами языка, а не с произвольными синтаксическими конструкциями. К примеру, лишп. В лишпе макросы могут работать только с s-exp.
Хуюпиель*
Имбецилы переизобрели лисп. Спешите видеть.
ОП, как мне статически тайпчекнуть то что оно высрет в итоговой программе? Ведь я пишу только исходную программу. Без этого твой язык мне не нужен.
Второе: допустим я написал траспилятор на твоём языке. Потом траспильнул вторым транспилятором. Где гарантии типобезопасности на target?
сделай нормально, иначе можно и на racket макросы бомбить
> как мне статически тайпчекнуть то что оно высрет в итоговой программе?
Статический тайпчек это тоже самое что синтаксический анализ. Статический тапочек доказывает над термами, а синтаксический анализ доказывает над синтаксическими конструкциями переводя их в термы.
Предположим, что мы имеем правило Natural (его определение опустим).
Тогда определение операции (+) над Natural будет очевидным:
Natural :: |x : Natural| + |y : Natural| => (+ |x| |y|)
Таким образом мы можем проверить статично не только синтаксическую корректность кода, но и семантическую.
Однако, не скрывая правды, target не обязан быть корректным. Если Source и Target представляют из себя Тьюринг-полный языки, то нельзя исключить левую рекурсию. Как ты понимаешь, это не проблема Yupiel, а проблема остановки.
К тому же есть очень большой, но никаким образом неразрешимый минус статичной типизации - все данные поступаемые извне невозможно проверить статично. Для этого придется добавлять тайпчек в рантайм. Для говноязыков, типа js, придется создавать функции-предикаты и оборачивать ими input-эффекты. Для языков с встроенной сильной системой типов, можно обойтись и нативным для этого языка тайпчеком.
Важно так же отметить, что Yupiel - гибкая штука. Она не накладывает никаких ограничений на код. Нормально делай - нормально будет.
К примеру, для надежной системы нужно соблюсти следующие паттерны:
- Отделить выражения и эффекты.
Не допустить конструкции вида ‹print(x) + print(print(y))›
Есть выражения, которые что-то возвращают, а есть действия/эффекты, которые что-то делают, но сами ничего не возвращают. Взболтать но не смешивать.
- Запретить общую рекурсию.
Если в Source-язык не может в общую рекурсию, то есть четкие гарантии того, что твой код не упадет в бесконечную петлю.
Используй только структурную рекурсию над конструкторами, и соответствующие комбинаторы для этого.
Lisp вообще не про это.
Первое - все лиспы имеют рантайм. Нет лиспа без рантайма. Это сразу выносит на нет возможности бесшовной транспиляции.
Второе - лисп, как и все остальные языки, ограничен синтаксисом, а именно s-exp. Если начнешь расширять s-exp кастомным парсером, то просто создашь ограниченную версию Yupiel.
Третье - лисп это язык (хоть и с мощным метапрограммированием). Yupiel - это метаязык. Как EBNF.
А то.
Несешь бред. Грамматика нулевого уровня типа Semi-Thue это иная, очень упрощённая концепция, и что важно неюзабельная концепция. Погугли Thue lang. Yupiel использует CFG (Context Free Grammar), а это нихуя не нулевой уровень.
> Pattern => Replacement
У тебя нет ни ограничения по длине слов, а значит это уже не уровень 1, и хотя про уровень 2 уже нельзя говорить, у тебя
> Pattern - набор символов и нетерменалов.
нет ограничений по нетерминалам слева, какой нахуй контекст фри граммар.
В любом случае, советую почитать про нормальный алгоритм Маркова, мб, ты переизобретаешь велосипед, только корявый.
> нет ограничений по нетерминалам слева, какой нахуй контекст фри граммар.
Реплейсмент идет ровно до \n.
> алгоритм Маркова
Та же хуйня, что и система Semi-Thue, только в профиль. Ты сам на них программировать пробовал?
> нет ограничений по нетерминалам слева, какой нахуй контекст фри граммар.
В случае паттерна, исключением из символов является соответственно (=>). Если нужно использовать (=>) как символ используй экранирование (\=>). Тоже касается табов (\t), перевод строки (\n). Так же, для удобства один символ пробела (" ") считается за (whitespace+).
Т.е паттерн "print x" соответствует "print x", так и "print x".
Для понимания треда:
- Полнота по Тьюрингу.
- Иерархия Хомского.
- Система переписывания.
- Парсинг.
- Алгоритм Маркова и Semi-Thue (Грамматики типа 0).
- Метапрограммирование
> Ииииии, мы изобрели s-expressions.
Я действительно не понимаю где тут связь.
Чтобы вы поняли, что такое Юпиэль, я приведу пример программы.
# модуль HelloWorld.ypl
Effect :: say |n : Note|! => console.log("|Hi World|")
Letter :: |x : or C D E F G B A|
Octave :: |x : 1 2 3 4 5 6 7 8|
Note :: |l : Letter||o : Octave| => note("|l|", |o|)
# source source.txt
say C4!
# после запуска в консоли "yupiel -m HelloWorld -s source.txt -t target.js" в папочке с проектом появится target.js с таким содержанием:
console.log(note("C", 4))
Теперь понятно, что такое Юпиэль?
> Твой яп наверное не в вакууме работает а в каком-то вычислительном устройстве "рантайме".
Хех, у него действительно нет рантайма. Юпиэль не знает ни о операции (+), ни о IO. Юпиэль занимается транспиляцией только и всё, соответственно "паразитируя" на других языках. Как в примере выше. Используется встроенная в js console.log. Можно транслировать в какой хочешь язык.
И в чём основное преимущество такого подхода перед обычными языками? Только сформулируй по делу самый главный тезис
> И в чём основное преимущество такого подхода перед обычными языками?
Всё предельно просто - тотальная универсальность. Yupiel можно использовать буквально везде. Это всё сочетается с тем, что ты делаешь язык под код, а не код под язык. Можно писать действительно человеко-читаемый код на языке который больше подходит задаче проекта, чем какой-либо язык общего назначения.
Нет проблем с производительностью самих DSL. Можешь транслировать либо в C, либо в какой-нибудь Python, или даже в ASM. Производительность зависит от выбранного Target и от прямости рук самого программиста.
спасибо за ответ, ОП.
Извини, что я плохо во всём таком разбираюсь. У меня есть только хотелки сумелок нет
Хотелка 0 (?):
Мне всё-таки кажется что я хочу корректный таргет. Понятно, что source программу я не смогу запустить, а только таргет. Если некорректно был написан сорс, то запуск таргета может выдать непонятную балалайку в консоль и ищи свищи где в сорсе ошибка. Там же будет в этом юпиэле тайп инфиренс, хиндли милнер вот это всё? Я правильно понимаю, что нормальные сообщения об ошибках невозможно получить, так как это проблема останова уже?
Хотелка 1:
Так как это языко-ориентированный язык, хочу писать собственные DSLы (например JSON-подобные (в которых будут в том числе enumerable типы полей)), хочу под каждый такой dsl сгенерированный language server, чтобы в редакторе мне подсказочки выдавало при написании на таком dsl, и говорило валидный у меня файл или невалидный, выдавало где ошибочки. DSL безо всяких вычислений, чисто декларативная простыня чтобы для конфигов. Сможет ли юпиэль в такое?
Я знаю существует Xtext и Jetbrains MPS. Но они выглядят всратыми, даже лень осиливать такое. Кроме того они требуют целые IDE.
Хотелка 2:
хочу писать и запускать домэйн специфик стэйт машины. Xtext такое кажется умеет
Вопрос:
Сущестует ли что-то более лайтвэйт на рынке чем xtext и mps? Просто лень эти читать простыни из документации для того чтобы написать dsl уровня "пук-среньк"
Похвалить:
У юпиэль отличная маркетинговая стратегия: собирать лидов на три строчки синтаксиса
> Хотелка 0 (?):
Надо еще думать о возможности создавать прозрачный для кода дебаг. Сильной стороной Yupiel является (будет) прозрачная встраиваемость. Что если в рантайме появился эксепшен? Как фиксить? Над этим стоить думать. Решением может быть:
- На этапе создания DSL: юнит-тесты языка.
- На этапе использования DSL: зависимые типы.
> Хотелка 1:
Будет поддержка Yupiel в каких-нибудь VSCode. Если где-то появилась синтаксическая ошибка, редактор пометит. Для всех остальных фич редакторов не может быть универсального решения. Можно только создать универсальный формат для написания документации, откуда его можно будет транслировать в специфичный формат редактора.
> Вопрос:
Ну, я знаю Racket. Но там тоже ахуеешь всю документацию языка читать.
Единственным решением является, ВНЕЗАПНО, Юпиэль. Не просто так я её решил создать. Если бы был, хотя бы даже шизотреический, язык с свойствами схожими с Юпиэль, то мысль о создании этой утилиты у меня даже бы не появилась.
> У юпиэль отличная маркетинговая стратегия: собирать лидов на три строчки синтаксиса
Хех, это да. Лиды делают DSL, джуны на этих DSL пишут.
> Хех, у него действительно нет рантайма. Юпиэль не знает ни о операции (+), ни о IO. Юпиэль занимается транспиляцией только и всё
Это слишком тупой троллинг.
х86 цп знает что такое транспиляция? А +- он знает. Так КАК твой дупель делает транспиляцию на железе с +- и без транспиляции?
Ты на какой доске вообще решил дерьма в уши людям лить придурок?
Ты компиляцию от рантайма отличаешь? Ясен хуй, что транспилятор/компилятор это программа, которая запускается на компьютере. Однако с рантаймом это не связано. Есть этап компиляции/транспиляции, есть рантайм. Yupiel занимается только транспиляцией. Что там в рантайме произойдет уже не забота Юпиэль, а забота какого-то другого компилятора/интерпретатора (V8, ghc, python, к примеру).
>>22235
> Учи лисп.
Чел, я пишу прототип Yupiel на Racket.
Лисп и Yupiel это совершенно разные языки.
Ты где вообще взаимосвязь нашел?
Выглядит как типичный лисп.
>>22243
> Чел, я пишу прототип Yupiel на Racket.
Ты используешь лисп для создания dsl чтобы сделать dsl для создания dsl.
> Ты компиляцию от рантайма отличаешь?
Окей, я немного протупил.
Так есть лиспы компилируемые в С, и что теперь?
Ну то есть чисто академически забавно конечно. Но ты реально лисп переизобретаешь, тебе нужно ещё время просто.
>>21153
По-моему у тебя ошибка в коде.
Интересно как в юпеле записать что в случае чисел от 10 до 20 делать одно, а в случае от 21до 23 другое. Ну например это часть имени функции - делать21 например.
Или как простейшую типизацию описать.
> Но ты реально лисп переизобретаешь
Блядь. Дай хоть один аргумент, почему Yupiel это Lisp?
> Интересно как в юпеле записать что в случае чисел от 10 до 20 делать одно
Сначала опишем лямбда-терм, будем использовать JS как таргет.
Lambda |A| -> |B| :: λ |v : Var| . |e : define |v| as |A| in |e : |B||| => ((|v|) => |e|)
Define |Pattern| as |Type1| in |Expr : Type2| определяет правило |Type1| для паттерна локально для выражения |Expr|.
Отлично. Теперь определим функции (>) и (<).
Boolean :: |Number| > |Number|
Boolean :: |Number| > |Number|
Теперь определим функцию (if):
|A| or |B| :: if |e : Boolean| then |A : Expr| else |B : Expr|
Теперь определим (and):
Boolean :: |Boolean| and |Boolean|
Определим дунофинг:
Nothing :: do nothing => null
Ну, а теперь выполняем то, что просил.
λ x . if x > 10 and x < 20 then do nothing else do nothing
Конечно, правила можно было бы сделать рекурсивными. Тогда Yupiel было Тьюринг-полной, и пикрилейтед-код был бы допустимым в Yupiel. Однако, хоть пикрилейтед невероятно элегантен, если слишком много «против» против рекурсивных правил.
> Но ты реально лисп переизобретаешь
Блядь. Дай хоть один аргумент, почему Yupiel это Lisp?
> Интересно как в юпеле записать что в случае чисел от 10 до 20 делать одно
Сначала опишем лямбда-терм, будем использовать JS как таргет.
Lambda |A| -> |B| :: λ |v : Var| . |e : define |v| as |A| in |e : |B||| => ((|v|) => |e|)
Define |Pattern| as |Type1| in |Expr : Type2| определяет правило |Type1| для паттерна локально для выражения |Expr|.
Отлично. Теперь определим функции (>) и (<).
Boolean :: |Number| > |Number|
Boolean :: |Number| > |Number|
Теперь определим функцию (if):
|A| or |B| :: if |e : Boolean| then |A : Expr| else |B : Expr|
Теперь определим (and):
Boolean :: |Boolean| and |Boolean|
Определим дунофинг:
Nothing :: do nothing => null
Ну, а теперь выполняем то, что просил.
λ x . if x > 10 and x < 20 then do nothing else do nothing
Конечно, правила можно было бы сделать рекурсивными. Тогда Yupiel было Тьюринг-полной, и пикрилейтед-код был бы допустимым в Yupiel. Однако, хоть пикрилейтед невероятно элегантен, если слишком много «против» против рекурсивных правил.
> Первое - все лиспы имеют рантайм. Нет лиспа без рантайма. Это сразу выносит на нет возможности бесшовной транспиляции.
Есть лиспы, которые паразитируют транспилируются в другие языки, та же Clojure, Fennel.
Пиздос, а не легче самим ручками написать в .js файле console.log чем описывать его в каком то юпель несколькими строками кода, которые ещё и хуй поймёшь как работают
> Пиздос, а не легче самим ручками написать в .js файле console.log
Это просто пример. Понятное дело, Yupiel нужно для простого создания DSL.
>В языке есть только одна конструкция - правило. Вся программа на Юпиель представляет из себя список правил вида: Type :: Pattern => Replacement или Type :: Pattern
>первый пример: какие-то стрелки, ООП
Быстро ты сломался, как и твой недо-пролог с уебищной парадигмой.
> ООП
Чел, у тебя каша в голове. Какой еще ООП? Ты где его увидел?
Да и прологом Yupiel не является, хотя имеется логический вывод (переменные логические) для того чтобы разрешать типы.
> какие-то стрелки
Сначала изучи Term Rewriting. Yupiel это про Term Rewriting. Когда познаешь Лямбду и перезапись терминов, тогда приходи.
Ты переизобрел алгоритм маркова и назвал его своим ЯП?
Алгоритм Маркова это совершенно иная вещь, сколько раз объяснять.
В Нормальном Алгоритме Маркова паттерны рассматриваются по полному точному соответствию. То есть в алгоритме Маркова у правил нет параметров и переменных.
Простой пример:
Пусть будет правило (a ->. b), тогда применив его к (aab) мы получим (bbb)
Но возьмем задачку посложнее:
Написать такую функцию, которая меняла свои аргументы местами: (swap x y) -> (swap y x).
В алгоритме Маркова это невозможно выполнить очевидным способом, потому что нет понятия о переменных и параметрах функций.
Алгоритм Маркова это Тьюринг-полная грамматика, который важен так же как и брейнфак.
Напротив, Yupiel не является Тьюринг-полной (по понятной причине). У правил Yupiel есть параметры, и с помощью их можно обрабатывать конечные рекурсивные структуры, что делает их CFG.
>X0:
>Решением может быть:
>- На этапе использования DSL: зависимые типы.
вот это пожалуйста. можно? голосую за зависимые типы
>X1:
>Будет поддержка Yupiel в каких-нибудь VSCode.
Требуется поддержка не самого юпиел в вскод а автоматическая поддержка созданного dsl. Понятно, что скорее всего одним ypl не обойтись
надо вот так чтоб:
https://youtu.be/5WA8kCdg6Ek?t=997
и как-то так
https://youtu.be/ESRk7NmCDFA?t=608
>Хех, это да. Лиды делают DSL, джуны на этих DSL пишут.
I mean https://en.wikipedia.org/wiki/Lead_generation
> Racket
>я пишу прототип Yupiel на Racket.
А пакеж сорсы. Интересно
> Требуется поддержка не самого юпиел в вскод а автоматическая поддержка созданного dsl
А в чем принципиальная проблема? Не всё сразу, конечно. Но автоматизация всей рутины, это то, чем должен заниматься программист в первую очередь.
> А пакеж сорсы.
К сожалению, оставил зарядку от ноута в общаге. Сам иногда удивляюсь своей неряшливости. Однако, истины ради, не сказать, что я там успел что-то значимое сделать. Я сначала хотел адаптировать Nearley-parser для своих задач, но это сложнее (хотя прототип почти рабочий и хеллоуворд отрабатывает), проще самому Earley алгоритм имплементировать в Racket.
Еее, хоть что-то интересное на этой доске появилось.
/поридж-тред
> говно на нейронках
Ты серьезно? Ты вот сейчас реально серьезно, блядь? Мне даже не хочется объяснять тебе, почему твое говно - говно, но так уж и быть, объясню.
Во-первых, нейронки не предназначены для прувинга. Нейронка - черный ящик, допускающий неточность.
Во-вторых, нейронка не универсальна. Её надо будет дообучать, чтобы она смогла хоть как-то что-то да выдать.
В-третих, transcoder нужен для транспиляции существующих языков программирования. Ты не сможешь использовать его для создания DSL (а Yupiel создаётся именно для этого). Для нейрнок требуется нормальный такой датасет, а где ты его найдешь для еще не созданного DSL?
Гонору много, а сам нихуя не разумеет.
> DSL
Боярское программирование, лол. Что тебе мешает определить что угодно через дефайн и использовать для любой предметной области любой язык общего назначения? Насчёт неточности нейросетей, зря ты веруешь, что rule-based transpiler будет сильно точнее.
> Что тебе мешает определить что угодно через дефайн
Ты про #define? Это достаточно хреновый инструмент, на самом деле.
> предметной области любой язык общего назначения?
Который, естественно, привязан к своей экосистеме? Нет, спасибо.
> Насчёт неточности нейросетей, зря ты веруешь, что rule-based transpiler будет сильно точнее.
"Rule-based" означает, что система завязана на точной математической логике. Я даже планирую добавить в STD Yupiel рационалы, вместо дырявых float.
>>23832
> Ты только что PEG.
Так Юпиэль это CFG, я уже весь тред это говорю. Можно сказать, что Yupiel это продукт, как NPM к примеру. Пакетные менеджеры и до этого существовали, никто же не говорит, что NPM Inc. создало велосипед. Когда создавалась Scala никто не говорил, что разработчики Scala изобрели ФП, тоже самое с Clojure и Racket.
Алсо, Yupiel это не PEG. В PEG невозможны создания грамматик с левой рекурсивной частью типа: Expr -> Expr "*" Expr, а в Yupiel возможны, потому что под капотом Earley, а не PEG.
Ты только что Yupiel. Правда у Ypl как DSL крайне широкое применение.
> Я так понимаю пока что:
> LispMacro :: s-exp --> s-exp
> YPL :: ypl-expression --> any_target
Нет.
any_target + YPL :: ypl-expression --> any_target
Зачем ты изобрел лисп?
Лисп изобретать не устал?
мимовкатыш
> можно сделать быстрее регулярками на перле
Если смешать регулярки с перлом. Но там ебейшая темная магия происходит. И нет, не быстрее, потому что грамматики могут быть весьма сложными, а твой код будет полон синтаксического мусора. Как в своей грамматике разбираться будешь?
Так и не понял, зачем автор изобрёл ещё один лисп.
А пока вы читаете ваши хуерархии хуёмского, нормальные люди зарабатывают деньги на Javascript. Поссал на задротов.
Вебмакака, спок.
Очень просто.
Пока вы пытаетесь сделать POC я уже все на жс написал
Мда, будь я ОПом мне было бы очень обидно и стыдно - когда твою идею реализуют за вечер, пока ты дрочишься с ракетом и споришь в треде...
Чел, у тебя есть один огромных размеров прокол. У тебя там синтаксис должен соответствовать синтаксису хаскелла.
Аннет, ты парсишь правила через parsec.
Оно вообще делается на голом Хаскеле:
import Text.Parsec hiding (letter)
main = either (putStrLn . show) (putStrLn) . parse effect "-" =<< getContents
effect = do { string "say"; spaces; n <- note; string "!"; () ==> "console.log(" ++ n ++ ")" }
letter = l oneOf "CDEFGBA"
octave = l oneOf "12345678"
note = do { l <- letter; o <- octave; () ==> "note(\"" ++ l ++ "\", " ++ o ++ ")" }
l p a = do { c <- p a; return $ c:[] }
infixl 0 ==>
_ ==> b = return b
Да вообще на любых парсер-комбинаторах.
Проблема всех этих метакомпиляторов в тулинге. Начиная от внятных сообщений об ошибках и заканчивая поддержкой редакторов. Что в Yacc, что в C preprocessor, что в шаблонизаторах, что в других подобных. Задумка ОПа, кстати, больше всего похожа на OMeta. У которой была та же проблема с тулингом, и которая в итоге выродилась в никому ненужный Ohm. JetBrains придумали MPS и вроде сделали автогенерацию тулинга, но у них там вообще всё своё, включая уёбищный редактор. Впрочем, я давно его смотрел, не знаю, как сейчас.
> Если все равно нужно все писать вручную, тогда не ясно, чем это
Чтобы сделать ПРАВИЛЬНЫЙ язык, даже если он транспилируется в НЕправильный язык (C++, JS).
>Тогда определение операции (+) над Natural будет очевидным:
>Natural :: |x : Natural| + |y : Natural| => (+ |x| |y|)
сразу видно академического опущенца, ОЧЕВИДНО блять ему, ну давай напиши так программу строк тыща из этого очевидного кода
Это копия, сохраненная 23 июня 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.