Чому ми не зберігаємо синтаксичне дерево замість вихідного коду?


111

У нас багато мов програмування. Кожна мова розбирається і перевіряється синтаксис перед тим, як перевести його в код, щоб побудувати абстрактне синтаксичне дерево (AST).

У нас є це абстрактне синтаксичне дерево, чому б ми не зберігали це дерево синтаксису замість вихідного коду (або поруч із вихідним кодом)?

Використовуючи AST замість вихідного коду. Кожен програміст в команді може серіалізувати це дерево на будь-яку мову, яку хоче (з відповідною граматикою контексту) і проаналізувати AST після їх закінчення. Таким чином, це усуне дискусію щодо питань стилю кодування (де поставити {і}, куди помістити пробіл, відступ тощо)

Які плюси і мінуси такого підходу?


37
Lisp зазвичай пишеться як абстрактне синтаксичне дерево. Це не причепилося до більшості мов, схожих на алголь.
Девід Торнлі

2
Я не можу повірити, що Девід єдиний, хто згадує, що програми LISP - це абстрактне синтаксичне дерево.
WuHoUnited

3
Окрім інших моментів: AST - це навіть не остаточна річ. Для створення AST з коду також не потрібно багато часу. Коли я запускаю StyleCop на своєму маленькому проекті VS2010, він дуже швидко запускає десятки різних правил на основі AST на тисячах рядків коду (іноді на секунду чи дві). Також досить просто розширити StyleCop і написати власне правило. Я підозрюю, що розбір вихідного коду в AST - це добре зрозуміла і порівняно проста проблема. Це, в першу чергу, гарна мова, оптимізація, і всі бібліотеки, які важкі, не розбирають.
Робота

1
Після проаналізовано коду, це не так легко генерувати код для іншої мови. (Як би ви перевели неявне об'єднання Пролога в C?). Переважно те, що у вас є AST для оригінальної програми.
Іра Бакстер

3
Проблема синтаксичного розбору добре зрозуміла в технічному плані, але це непросте завдання для розбору C або C ++, оскільки вони брудні неприємні мови. Багато компіляторів розбирають C або C ++ на AST: Clang, GCC, ... Вони не призначені для зберігання програми, і GCC погано хоче бути компілятором, а не інструментом аналізу програм. Наш інструментарій для реінжинірингу програмного забезпечення DMS аналізує багато діалектів C і C ++, виробляє AST, символьні таблиці та різні види артефактів аналізу потоків. Великим профілем цього підходу є здатність до створення автоматизованих інструментів змін. semanticdesigns.com/Products/DMS/DMSToolkit.html
Іра Бакстер

Відповіді:


72

Пробіли та коментарі

Зазвичай AST не включає пробіл, лінійні термінатори та коментарі.

Змістовне форматування

Ви впевнені, що в більшості випадків це є позитивним (виключає форматування святих воєн), є багато випадків, коли форматування оригінального коду передає певний сенс, наприклад, у багаторядкових літеральних рядках та "кодових абзацах" (розділяючи блоки висловлювання з порожнім рядком).

Код, який неможливо скласти

Хоча багато парсери дуже стійкі до відсутнього синтаксису, код з помилками часто призводить до дуже дивного синтаксичного дерева, що є чудовим і денді до тих пір, поки користувач не перезавантажить файл. Ви коли-небудь помиляєтесь у своєму IDE, а раптом у всього файлу з'явилися "squigglies"? Уявіть, як це було б перезавантажено іншою мовою.

Можливо, користувачі не вводять незмінний код, але, безумовно, у них є необхідність зберігати локально.

Жодна дві мови не є ідеальними

Як зазначали інші, майже не існує двох мов, які мають ідеальний паритет. Найближчим, на який я можу подумати, є VB і C #, або JavaScript і CoffeeScript, але навіть тоді VB має такі функції, як XML Literals, які не мають цілком еквівалентів у C #, і перетворення JavaScript у CoffeeScript може призвести до появи багатьох літератур JavaScript.

Особистий досвід:

У програмному застосуванні, про яке я пишу, нам це потрібно зробити, оскільки очікується, що користувачі вводять "звичайні англійські" вирази, які перетворюються на JS у фоновому режимі. Ми розглядали лише можливість зберігання версії JS, але не знайшли прийнятного способу зробити це надійно завантаженим та вивантаженим, тому ми в кінцевому підсумку завжди зберігали як текст користувача, так і версію JS, а також прапор, який вказував, якщо "звичайний англійський" "версія проаналізована ідеально чи ні.


9
Є аналізатори, які фіксують коментарі та макет в AST. Наш інструментарій з реінжинірингу програмного забезпечення DMS робить це просто чудово. Це непросто з незаконним кодом; він має точний мовний аналізатор.
Іра Бакстер

2
Насправді існує інструмент, який перетворює Javascript у CoffeeScript , тому я думаю, що JavaScript і CoffeScript є взаємно перекладаються без літератур Javascript.
Пітер Олсон

Цікавий інструмент, Петре, я цього не знав.
Кевін МакКормік

+1 для змістовного форматування та цікавого особистого досвіду. - Білі простори не важливі для питання, і коментарі можуть бути збережені. Коди з помилками було б простіше виправити в будь-якому випадку, і, звичайно, частина однієї мови, щоб ними керувати всім, питання було недосяжним.
Крегокс

43

Чому б ми не зберегли це синтаксичне дерево замість вихідного коду? Кожен програміст в команді може серіалізувати це дерево на будь-якій мові, він хоче і проаналізувати AST, коли закінчив.

Дійсно, це розумна ідея. Майкрософт мав дослідницький проект у 1990-х роках, щоб зробити це майже точно .

На думку спадає кілька сценаріїв.

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

Другий цікавіший. Якщо ви можете зберігати абстрактне синтаксичне дерево, зміна, що відрізняється кодом, стає не текстовою, а швидше синтаксичною. Перебудовування, де переміщується код, стає набагато простішим для розуміння. З нижньої сторони, звичайно, написання алгоритмів, що відрізняються від дерева, не зовсім тривіально, і це часто доводиться робити на мові. Текстова різниця працює майже для будь-якого мови.

Третє більше схоже на те, що Симоній передбачав умисне програмування: що основними поняттями, спільними для мов програмування, є те, що серіалізується, і тоді ви маєте різні погляди на ці концепції, викладені різними мовами. Хоча гарна ідея, потворний факт полягає в тому, що мови є досить різними у своїх деталях, що підхід із найменшим загальним знаменником насправді не працює.

Отже, коротше кажучи, це чудова ідея, але це величезна кількість додаткової роботи для порівняно невеликої вигоди. Ось чому навряд чи хто це робить.


3
Власне, ви можете зробити дерево-різницею незалежно від мови. Для побудови дерев вам потрібні конкретні аналізатори для мови. Дивіться нашу лінійку інструментів Smart Differencer, що порівнюють AST для багатьох мов. Всі вони використовують один і той же базовий дифференціал. semanticdesigns.com/Products/SmartDifferencer
Іра Бакстер

1
Я сподіваюся, що колись побачу команду «Мій стиль-симпатична друк-завантаження» у візуальній студії «мій-гарненький друк-завантаження» ... сподівався роками ... ще не пощастило ...
Роман Старков

19

Ви можете стверджувати, що саме цей байт-код є в .NET. Програма рефлектора Infact redgate переводить байт-код назад у ряд мов програмування .NET.

Однак є проблеми. Синтаксис є мовою, якою є стільки, скільки є речей, які ви можете представити на одній мові, які не мають представлення на інших мовах. Це відбувається в .NET, коли C ++ є єдиною мовою .NET, яка має доступ до всіх 7 рівнів доступу.

Поза середовищем .NET стає набагато складніше. Потім кожна мова починає мати власний набір пов'язаних бібліотек. Неможливо було б відобразити загальний синтаксис як на C, так і на Java, які відображали одне й те саме виконання інструкцій, оскільки вони вирішують симуляційні задачі дуже різними способами.


5
Ви коли-небудь намагалися декомпілювати MSIL, створений F #?
SK-логіка

12

Мені подобається якась ваша ідея, але ви значно завищуєте, як легко перекласти мову на мову. Якби це було просто, вам навіть не потрібно було б зберігати AST, оскільки ви завжди можете розбирати мову X в AST, а потім переходити з AST до мови Y.

Однак я хотів, щоб специфікації компілятора бажали трохи більше розкрити деяку частину AST через якийсь API. Такі речі, як орієнтоване на аспекти програмування, рефакторинг та статичний аналіз програм, можна реалізувати через такий API, без того, щоб реалізатор цих можливостей мав потребу повторити таку роботу, яку вже виконали автори компілятора.

Дивно, як часто структура даних програміста для представлення програми є купою файлів, що містять рядки.


5
Ви слідкували за розробкою проекту " Рослін " від Microsoft, щоб відкрити компілятори VBc та C # як API? Доступна версія попереднього перегляду
Carson63000

11

Я думаю, що найбільш помітними є такі:

  • Користі немає. Ви сказали, що це означатиме, що кожен може використовувати свою домашню тварину. Але це неправда - використання зображення синтаксичного дерева дозволило б усунути лише синтаксичні відмінності, але не семантичні. Він певною мірою працює для дуже схожих мов - таких як VB і C #, або Java та Scala. Але навіть не там повністю.

  • Це проблематично. Ви здобули свободу мови, але втратили свободу інструментів. Ви більше не можете читати та редагувати код у текстовому редакторі чи навіть будь-якому IDE - це залежить від конкретного інструменту, який говорить про ваше AST-представлення як для читання, так і для редагування коду. Тут нічого не здобуто.

    Щоб проілюструвати цей останній пункт, погляньте на RealBasic, який є власною реалізацією потужного діалекту BASIC. Деякий час це мало схоже на те, що мова може знятись, але вона повністю залежала від постачальника, до того, що ви могли переглядати код лише в їх IDE, оскільки він був збережений у фірмовому нетекстовому форматі. Велика помилка.


4
Потенційна вигода полягала б у тому, що вона може закінчитись нескінченними дебатами, такими як "вкладки проти пробілів", "unix проти вікна зміщення / відступ", "префікси m_ перед членами чи ні", оскільки їх можна перетворити на прості параметри IDE.
nikie

1
@nikie Правда, але ви вже можете це зробити за допомогою інструментів переформатування - як-от astyleUn UniversalalIndent. Немає необхідності в прихованих бінарних форматах.
Конрад Рудольф

2
Справжньою вигодою буде потенціал використання інструментів diff / patch, які дозволять краще зрозуміти, що насправді змінилося. Але це, мабуть, означає, що для контролю версій потрібен цілий новий ланцюжок інструментів, що є серйозним обмеженням.
Пітер Тейлор

1
Якщо ви думаєте, що "користі немає", ви не бачили доменного верстата доменного програмного забезпечення.
Craig Stuntz

1
У двох словах, та ж логіка може проектуватися в різні подання, а не на всіх текстах, роблячи правила доступними для непрограмістів. Наприклад, фахівці з домену, як актуарії, можуть написати актуарні частини страхової заяви. Як DSL, за винятком того, що не обмежується цим представленням. Однак це дуже пов'язане з питанням. Там хороша демонстрація .
Крейг Стунц

6

Я думаю, якщо ви зберігаєте і текст, і AST, ви насправді не додали нічого корисного, оскільки текст вже є однією мовою, і AST можна швидко відновити з тексту.

З іншого боку, якщо ви зберігаєте лише AST, ви втрачаєте речі, такі як коментарі, які неможливо відновити.


6
і якщо ви зробите коментарі частиною синтаксичного дерева (з вузлами коментарів, які можуть бути дочірнім)?
храповик виродка

Наші інструменти роблять саме це. Дивіться інші мої коментарі в цій темі.
Іра Бакстер

4

Я вважаю, що ідея цікава в теорії, але не дуже практична, оскільки різні мови програмування підтримують різні конструкції, деякі з яких не мають еквівалентів в інших мовах.

Наприклад, X ++ має висловлювання "while select", яке неможливо записати в C # без великої кількості зайвого коду (додаткові класи, додаткова логіка тощо). http://msdn.microsoft.com/en-us/library/aa558063.aspx

Я тут говорю, що в багатьох мовах є синтаксичні цукри, які перекладаються у великі блоки коду тієї самої мови або навіть елементи, які взагалі відсутні в інших. Ось приклад, чому підхід AST не працює:

Мова X має ключове слово K, яке перекладається в AST у 4 висловлюваннях: S1, S2, S3 та S4. Тепер AST перекладається мовою Y, а програміст змінює S2. Тепер, що відбувається з перекладом назад до X? Код перекладається як 4 твердження замість одного ключового слова ...

Останній аргумент проти підходу AST - це функції платформи: що відбувається, коли функція вбудована в платформу? Як і .NET’s Environment.GetEnvironmentVariable. Як ви це перекладаєте?


4

Навколо цієї ідеї побудована система: JetBrains MPS . Редактор трохи дивний, або просто інший, але загалом це не така велика проблема. Найбільша проблема, добре, що це не текст більше, тому ви не можете використовувати будь-якого зі звичайних текстових інструментів - інші редакторів, grep, sed, злиття і диференціалів інструментів і т.д.


2
... але ви отримуєте безліч функцій редактора поза коробкою. Подумайте про те, щоб трохи розширити цю відповідь, це дуже цікава технологія, яка заслуговує на детальне ознайомлення з перевагами не зберігання вихідного коду як тексту. Наприклад, коли я відповідав на це запитання на вкладках та пробілах .
Стівен Євріс

AST можна зберегти у читаному для людини форматі, а не у двійковому. Ви можете, наприклад, за допомогою інструментів linux замінити кожен метод у коді, який приймає за параметр об'єкт, який може бути серіалізуючим? писати було б дуже важко, але AST зробити це дуже просто.
IAdapter

1
Люди постійно роблять цю помилку. AST робить це простіше, ніж якщо у вас є просто необроблений текст. Але для всього цікавого вам потрібна купа додаткової інформації: контроль та потік даних, таблиці символів, аналіз діапазону, ... AST допомагають, але є лише невеликою частиною того, що дійсно потрібно.
Іра Бакстер

@Ira Baxter, звичайно, простіше з AST. Але значно важче інтегруватись у існуючу інфраструктуру.
SK-логіка

4

Насправді є декілька продуктів, загальновідомих як "мовні робочі стійки", які зберігають AST і представляють у своїх редакторах "проекцію" AST назад на певну мову. Як сказала @ sk-logic, MPS JetBrains 'є однією з таких систем. Інший - Intentional Workbench від Intentional Software.

Потенціал для мовних робочих місць здається дуже високим, особливо в області доменних мов, оскільки ви можете створити проекцію, що залежить від домену. Наприклад, навмисна демонстрація DSL, що стосується електричної енергії, що проектується як схема, набагато простіше та точніше для обговорення та критики доменного експерта, ніж схема, описана на текстовій мові програмування.

На практиці мовні робочі стійки досить повільно втягуються, оскільки, окрім роботи з DSL, розробники, напевно, вважають за краще працювати на звичній загальній мові програмування. Якщо порівнювати голову до тексту з текстовим редактором або програмуванням IDE, мовні верстаки мають багато накладних витрат, і їх переваги не є настільки очевидними. Жодна з мовних робочих груп, яку я бачив, не зав'язала себе під час завантаження, до того моменту, коли вони можуть легко розширити власні IDE, тобто - тобто якщо мовні робочі верстати чудово підходять для продуктивності, чому б не покращилися інструменти мовних верстаків. -і - краще за швидшими та швидшими ставками?


"мовний робочий стіл" не обов'язково повинен базуватися на зберіганні сирих AST. Вони також можуть бути орієнтовані на синтаксис простого тексту, дивіться, наприклад, meta-alternative.net/pfront.pdf (а цей фактично розширює редактор Visual Studio та Emacs з будь-яким eDSL, реалізованим поверх нього).
SK-логіка

Це цікавий папір; це нагадує мені (за бажанням, зовсім не для реалізації) інструмент під назвою SugarJ, який був представлений на SPLASH / OOPSLA кілька тижнів тому: uni-marburg.de/fb12/ps/research/sugarj
Larry OBrien

цікаво, я спробую і цей.
SK-логіка

3

Ви читали мою думку.

Коли я пройшов курс компіляторів, кілька років тому я виявив, що якщо взяти AST і серіалізувати його, з позначенням префікса замість звичайного позначення інфіксації, і використовувати дужки для розмежування цілих висловлювань, ви отримуєте Lisp. У той час як я дізнався про схему (діалект Лісп) у моїх студентських студіях, я ніколи насправді не оцінив її. Я безумовно вдячний Лісу та його діалектам, як результат цього курсу.

Проблеми з пропозицією:

  1. важко / повільно скласти AST у графічному середовищі. Зрештою, більшість з нас може набрати швидше, ніж ми можемо рухати мишкою. І все ж виникає питання "як написати програмний код планшетом?" Введення на планшеті повільне / громіздке порівняно з клавіатурою / ноутбуком із апаратною клавіатурою. Якщо ви могли створити AST, перетягуючи компоненти з палітри на полотно на великому сенсорному екрані, програмування пристрою на планшеті може стати справжньою справою.

  2. мало / жоден з наших існуючих інструментів це підтримує. У нас десятиліття розвитку завершилися створенням все складніших IDE та все більш інтелектуальних редакторів. У нас є всі ці інструменти для переформатування тексту, порівняння тексту, пошуку тексту. Де знаходяться інструменти, які можуть виконувати еквівалент звичайного пошуку виразів по дереву? Або різниця двох дерев? Всі ці речі легко зробити з текстом. Але вони можуть лише порівняти слова. Змініть ім’я змінної так, щоб слова були різними, але смислове значення було однаковим, і ці різні інструменти можуть зіткнутися з проблемою. Такі інструменти, розроблені для роботи над AST замість тексту, дозволять вам наблизитися до порівняння смислового значення. Це було б гарною справою.

  3. в той час як перетворення вихідного коду програми в AST є відносно добре зрозумілим (у нас є компілятори та інтерпретатори, чи не так?), перетворення AST у програмний код не дуже добре зрозуміло. Помноження двох простих чисел для отримання великого, складеного числа є відносно простим, але множити велике, складене число назад на прості кошти набагато складніше; ось де ми знаходимось з розбором проти декомпіляції AST. Ось де різниця між мовами стає проблемою. Навіть у межах певної мови існує кілька способів декомпілювати AST. Ітерація через колекцію предметів і отримання якогось результату, наприклад. Використовувати цикл, повторюючи масив? Це було б компактно і швидко, але є обмеження. Використовуйте якийсь ітератор, працює над колекцією? Ця колекція може бути змінного розміру, що додає гнучкості за (можливий) рахунок швидкості. Карта / зменшення? Більш складний, але неявно паралельний. І це тільки для Java, залежно від ваших уподобань.

З часом зусилля з розробки будуть витрачені, і ми будемо розвиватися за допомогою сенсорних екранів та AST. Введення тексту стане менш необхідним. Я бачу, що сьогодні це є логічним прогресом, де ми знаходимось, дивлячись на те, як ми використовуємо комп’ютери, це вирішить №1.

Ми вже працюємо з деревами. Лісп - це просто серіалізовані АСТ. XML (і HTML за розширенням) - це просто серіалізоване дерево. Для пошуку у нас вже є пара прототипів: XPath та CSS (для XML та HTML відповідно). Коли будуть створені графічні інструменти, які дозволяють нам створювати селектори та модифікатори стилів CSS, ми вирішили частину №2. Коли ці селектори можуть бути розширені на підтримку регулярних виразів, ми будемо ближче. Ще шукаємо хороший графічний інструмент для порівняння двох XML або HTML документів. Коли люди розроблять ці інструменти, №2 буде вирішено. Люди вже працюють над такими речами; їх просто ще немає.

Єдиний спосіб я бачу можливість декомпілювати ASTs на текст мови програмування - це щось, що прагне до мети. Якщо я змінюю існуючий код, мета може бути досягнута алгоритмом, який робить мій модифікований код максимально подібним до початкового коду (мінімальна текстова різниця). Якщо я пишу код з нуля, мета може бути найменшим, найкруткішим кодом (можливо, для циклу). Або може бути код, який паралелізує максимально ефективно (можливо, карта / зменшення чи щось із залученням CSP). Отже, той самий AST може призвести до істотно різного коду, навіть тієї ж мови, виходячи з того, як були поставлені цілі. Розробка такої системи вирішила б №3. Це було б обчислювально складно, це означає, що нам, мабуть, знадобиться якесь розташування клієнт-сервер,


1

Якщо ви маєте намір усунути дискусію щодо стилів форматування, то, можливо, те, що ви хочете, - це редактор, який читає у вихідному файлі, форматує його відповідно до ваших особистих уподобань для відображення та редагування, але, зберігаючи його, переформатує у вибраний стиль команда використовує.

Це досить просто, якщо ви використовуєте такий редактор, як Emacs . Зміна стилю форматування цілого файлу - це три командні завдання.

Ви також повинні мати можливість створити гачки для автоматичного перетворення файлу у ваш власний стиль при завантаженні та перетворення його у командний стиль при збереженні.


1
Тоді вам все одно знадобиться семантична диференція та злиття (тобто, знову-таки, рівень AST).
SK-логіка

Ні, редактор переформатовується назад у командному стилі для зберігання джерела - тому ви порівнюєте один тип джерела з тим же типом.
Густав Бертрам

Хороший момент, одне нормалізоване представлення вирішує всі проблеми
SK-логіка

1
Ні, він вирішує лише проблеми, пов'язані з розділенням двох файлів для ідентичності. Якщо ви хочете побачити відмінності між файлами, в ідеалі вам потрібно щось, що розуміє структуру. Я люблю своїх emacs, але він не розуміє структури.
Іра Бакстер

Emacs чудовий, але я ніколи не використовую його для розм. Щоб відрізняти своє початкове дерево перед реєстрацією, я завжди використовую meld . Він фактично розуміє SVN та git. У Windows я б використовував WinMerge, ймовірно, у поєднанні з черепахою.
Густав Бертрам

1

Читати та змінювати AST важко замість вихідного коду.

Однак деякі інструменти, пов'язані з компілятором, дозволяють використовувати AST. Байт-код Java та проміжний код .NET працюють аналогічно AST.


1
Надійніше модифікувати AST за допомогою механічних інструментів легше, ніж це робити з текстом. Це можна зробити за допомогою змін, спрямованих на шаблон. Дивіться semanticdesigns.com/Products/DMS/ProgramTransformation.html
Іра Бакстер

2
Розкажіть про це LISPers зараз ...
hugomg

@Ira Baxter. Я знаю, я насправді працюю над користувальницьким візуальним інструментом, який працює безпосередньо з AST, проте іноді розробникам доводиться працювати з текстом, а не візуальним. Деякі AST також представлені у вигляді скороченої мови програмування в тексті.
umlcat

@umlcat, чи можете ви розповісти більше про вашу роботу над візуальним інструментом для AST?
Даніель Альбусхат

@Daniel Albuschat Я працюю над проектом мови програмування для домашніх тварин. Аналізатору його важко реалізувати, тому я пропустив його на даний момент і створив інструмент, де я показую AST (форму з керуванням деревом) і додаю вирази безпосередньо. А можна зробити навпаки, генерувати код з AST.
umlcat

0

це приємна ідея; але AST кожної мови відрізняється від усіх інших.

Єдине відоме мені виключення для VB.NET та C #, де microsoft стверджує, що вони "абсолютно однакова мова з різним синтаксисом". Навіть інші мови .NET (IronPython, F #, що завгодно) відрізняються на рівні AST.

Те ж саме і з мовами JVM, усі вони націлені на один і той же байт-код, але мовні конструкції різні, що робить його різними мовами та різними AST.

Навіть мови тонкого шару, як CoffeScript та Xtend, поділяють багато теорії основних мов (JavaScript та Java відповідно); але запровадити концепції вищого рівня, які (або повинні бути) зберігаються на рівні AST.

якби Xtend можна було реконструювати з Java AST, я думаю, що це було б визначено як "uncipiler" від Java до Xtend, який магічно створює абстракції вищого рівня з існуючого коду Java, ви не думаєте?


1
Як хтось із близькими знайомими як із компіляторами C #, так і з VB, я можу вам сказати, що вони, безумовно, схожі, але є достатньо важливих деталей, які досить різняться, що розглядати їх як "ту саму мову з різним синтаксисом" недоцільно. Ми думали зробити це для проекту Roslyn; побудова єдиного компілятора, який міг би зрівняти обидві мови з однаковими можливостями - і після довгих дискусій вирішив перейти з двома компіляторами для двох мов.
Ерік Ліпперт

@EricLippert: це прикро. Не те, що я коли-небудь планував вивчати будь-яку мову, але це звучало як приємний виняток. Я думаю, що htat залишає lisp-like-Dylan та algol-like-Dylan як єдиний приклад "тієї самої мови з різними синтаксисами".
Хав'єр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.