Блог коричневого PLT

ПОПЕРЕДНІ ПОСТИ

рахунок

Мови для схуднення за рахунок зменшення цукру

Опубліковано 08 січня 2016 року.

JavaScript - це божевільна мова. Це визначається 250 сторінками англійської прози, і навіть ті частини мови, які повинні бути простими, такі як додавання та змінна сфера, дуже складні. Раніше ми показали, як вирішити цю проблему за допомогою λs5, що є прикладом того, що називається перевіреною семантикою.

Ви можете прочитати про λs5 за посиланням вище. Але основна ідея полягає в тому, що λs5 складається з двох частин:

  • Невелика основна мова, яка фіксує основні частини JavaScript, без усіх його недоліків, і
  • Функція знежирення, яка переводить повну мову до цього маленького ядра.

(Ми зазвичай називаємо цю основну мову λs5, хоча технічно кажучи, це лише частина того, що становить λs5.)

Ці два компоненти разом надають нам реалізацію JavaScript: щоб запустити програму, ви зменшуєте її до λs5, а потім запускаєте цю програму. І за допомогою цієї реалізації ми можемо запустити набір тестів на відповідність JavaScript, щоб перевірити правильність λs5: саме тому це називається перевіреною семантикою. І ось, λs5 передає відповідну частину набору відповідності test262.

Проблема

Однак кожна публікація в блозі потребує проблеми. Проблема з λs5 полягає у знебарвленні. Ми щойно заявили, що JavaScript є складним, тоді як основна мова для λs5 проста. Це означає, що ускладнення JavaScript слід розв’язувати не основною мовою, а натомість дезугаризацією. Візьмемо наочний приклад. Ось кілька невинних рядків JavaScript:

Ці пари рядків переходять у наступний код λs5:

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

Звичайне рішення

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

  • Усунення мертвого коду
  • Постійне складання
  • Постійне розповсюдження
  • Пропаганда псевдонімів
  • Перетворення призначення
  • Вбудована функція
  • Виберіть тип і усуньте статичні перевірки
  • Очистіть невикористані пов’язки навколишнього середовища

Більшість із них - це стандартні оптимізації підручників; хоча останні два специфічні для λs5. Як би там не було, ми все це зробили і отримали ... 5-10% кодова усадка.

Надзвичайне рішення

Це воно: 5-10%.

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

  • Призначений роздуття коду. Деякі з них є навмисними. λs5 - це невелика основна мова, і при перекладі на неї має бути певне розширення.
  • Випадковий здуття коду. Функція знежирення від JS до λs5 є простою функцією рекурсивного спуску. Це цілеспрямовано не розумно, і в результаті іноді генерує надлишковий код. І це саме те, від чого позбавляються щойно згадані перезаписи, що зберігають семантику.
  • Основне роздуття коду. Нарешті, деяка роздутість коду обумовлена ​​семантикою JS. JS - це складна мова зі складними функціями, і вони перетворюються на складний код λs5.

Шляхом зменшення передбачуваного чи випадкового роздуття коду було не багато. Але як ви вирішите зменшити роздуття основного коду? Ну, Essential bloat - це здуття коду, яке походить від ускладнень JS. Щоб його видалити, ви спростите мову. І ми зробили саме це! Ми визначили п’ять перетворень, що змінюють семантику:

  • (ІЧ) Відновлення ідентифікатора: робити вигляд, що JS має лексичний обсяг
  • (FR) Відновлення функцій: робіть вигляд, що функції JS - це просто функції, а не function-object-things.
  • (FA) Фіксована мірність: робіть вигляд, що функції JS завжди беруть стільки аргументів, скільки вони оголошені.
  • (ОАЕ) Виключення твердження: небезпечно видалити деякі перевірки виконання (ваш код і так правильний, так?)
  • (SAO) Спрощення арифметичних операторів: усунути дивну поведінку для базових операторів, таких як “+”.

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

Уроки про JavaScript

І ми можемо дізнатись про JavaScript з них. Ми реалізували ці перетворення для λs5, і тому ми могли запустити набір тестів із увімкненими перетвореннями і подивитися, скільки тестів зламано. Це дає грубу міру “правильності”: перетворення є правильним на 50%, якщо воно пробиває половину тестів. Ось графік:

Зверніть увагу, що трансформації, що змінюють семантику, зменшують код більш ніж на 50%: це набагато краще, ніж 5-10%, які давали семантикозберігаючі. Повертаючись до трьох видів роздуття коду, це показує, що більшість роздуття коду в λs5 є суттєвими: воно походить від складної семантики JS, і якщо спростити семантику, ви можете змусити її піти.

Далі, ось скорочення кожної з трансформацій, що змінюють семантику:

Оскільки ці трансформації, що змінюють семантику, є спрощеннями семантики JS, а знебарвлений розмір коду є мірою складності, ви можете розглядати цей графік як (грубу!) Міру складності особливостей мови. У цьому світлі зверніть увагу на ІЧ (відновлення ідентифікатора): він подрібнює інші перетворення, даючи зменшення коду на 30%. Це показує, що обсяг JavaScript є складним: за цією метрикою 30% складності JavaScript обумовлено його обсягом.

Винос

Ці трансформації, що змінюють семантику, дають семантичні обмеження на JS. Наша стаття робить ці обмеження точними. І вони є якраз тими спрощуючими припущеннями, які повинні робити документи, щоб міркувати про JS. Ви навіть можете завантажити λs5 з git і здійснити свій аналіз за λs5 з увімкненою підмножиною цих обмежень, і протестувати його. Тож давайте працюватимемо над майбутнім, де в статтях, які говорять про ІС, буде сказано, яку саме суб-мову ЖС вони означають.

Папір

Це просто тизер: щоб прочитати більше, див. Статтю.