Создаём своё подмножество javascript

от автора

image

В статье рассказывается про модуль позволяющий создавать подмножество javascript с любыми ключевыми словами. Строго для безудержного веселья.
На волне статьи про rucckuu.js я обзавидовался и решил обнародовать своё творение: небольшую экосистему для создания произвольных подмножеств javascript. Если к вам давно закрадывалась мысль о том, что некоторые ключевые слова плохо подходят к контексту их применения или мысль о том, что javascript слишком многословен (всякое бывает). Если вы хотите добродушно подшутить над коллегами или просто объяснить вашей маме чем вы всё-таки занимаетесь на работе, добро пожаловать под кат.

Итак, задача транспиляции сама по себе достаточно проста — найти и заменить. Сама же транспиляция в мире современного фронтенда — неотъемлемая часть интеграции новых технологий и спецификаций: все знают что такое babel или traceur-compiler, да и каждый уважающий себя фронтенд-разработчик время от времени поглядывает в рассылку esdiscuss. Молниеносное развитие нашего стека технологий — это боль и чудо в одном флаконе, потому что от возможностей захватывает дух, а от количества возможных вариаций исполнения у некоторых опускаются руки. Очень повезло тем, у кого они опускаются прямо на любимую или просто попавшуюся под них клавиатуру. Для таких бравых героев эта статья может представлять мало академического интереса, поэтому предостерегаю — всё нижесказанное предназначено только для удовлетворение безудержной страсти к созданию интересных штук. Да.

Вернувшись к транспиляции, задача по замене значений в строке очень тривиальна. Однако задача замены слов интегрированных с контекстом уже несколько более интересна. Не затрагивая все тысячи человеко-часов потраченных на изучение и создание теоретической базы для создания парсеров различных грамматик, перейдём сразу к самому главному. Грамматика языка программирования очень четко определяет контекст использования того или иного ключевого слова и это использование можно будет трактовать только одним, предопределенным способом. Такой детерминизм следует из самой сути программ, я уверен что нет никого, кто хотел бы видеть два разных результата исполнения одной и той же программы при одинаковых начальных условиях. Исходя из этого — любая программа может быть интерпретирована как весьма определённое синтаксическое дерево. Итак, для языков программирования достаточно просто обуздать синтаксического монстра и получить однозначное определение контекста использования любого слова. Имея на руках контекст — можно делать буквально что угодно.

Я думаю, многие слышали про esprima, парсер ECMAScript. Немного меньше людей знают про jison. Без первого мы бы не увидели jsx так скоро, а второй обязан своему появлению CoffeeScript, оба инструмента достаточно мощные, но esprima специализируется как раз на том, что мы хотим сделать — поменять внешний вид наших программ.

Скупое вступление окончено, к делу.

Создаем MeowScript

  • node, npm по моему предположению не вызывают у вас ужаса
  • npm i your-script в любую удобную директорию
  • заглянем в node_modules/your-script/lexems
  • создадим файл meowscript.lex
  • откроем javascript.lex из той же папки где-нибудь неподалёку
  • в meowscript.lex заменим определения ключевых слов на что-то вроде:

VAR meow LET meoww CONST meOw FOR meowwr ...

  • any-name.js

meowScript = new translator({     to: 'meowscript' });  let output = meowScript.parse(`     var kitty = new Kitty(); if (kitty.isHungry()) {kitty.feed()} `, {   from: 'javascript',   to: 'meowscript' });  console.log(output);  // stdout: // meow kitty = MEW Kitty(); meeow (kitty.isHungry()) {kitty.feed()} 

В общем, всё.
Область применения модуля ограничена вашим воображением. Под капотом находится как раз esprima, которую я уже упоминал, с тем исключением что эта версия пропатчена (вручную и с любовью) для того, чтобы поддерживать произвольный набор ключевых слов. Умолчу про объем труда, который пришлось проделать, чтобы вручную найти все hardcoded использования и заменить их на корректные референсы. После этого пришлось лишь добавить загрузчик для поддержки произвольной замены наборов ключевых слов во время исполнения. Работа достаточно простая, но кропотливая.
Помимо этого в комплекте упакован примитивный keyword провайдер с самым примитивным парсером .lex. Все модули валяются в свободном доступе и доступны для пинания всеми желающими

Фактически, с этим набором инструментов можно создавать произвольные подмножества javascript в течении нескольких минут. Единственное ограничение — неспособность модуля находить стандартные интерфейсы ноды или браузера. Так что увы, document.body.getBoundingClientRect, господа. Добавить поддержку транспиляции интерфесов тоже не так сложно, нужно всего лишь определить правила следования identifiers и осуществлять замену согласно им.

Напоследок, картинка в хедере поста неслучайна, как пример использвания your-script, я написал redscript — русское подмножество javascript. Ну и как следствие использования настоящего парсера:

var стр = 'var';

будет корректно транспилировано в:

пусть стр = 'var';

Сам модуль валяется в npm. Для затравки, пример транспилированной программы:

функция функ(икс, игрек, зет) {                              примем и = 0;                                   примем икс = {0: "ноль", 1: "один"};               примем функ = функция () {                       }                                               если (!и > 10) {                                    для (примем j = 0; j < 10; j++) {                   переключатель (j) {                                 положение 0:                                        значение = "zero";                                 стоп;                                       положение 1:                                        значение = "one";                                  стоп;                                   }                                               примем с = джей > 5 ? "ГТ 5" : "ЛЕ 5";         }                                           } иначе {                                           примем джей = 0;                                   попробуй {                                          пока (джей < 10) {                                     если (и == джей || джей > 5) {                            a[джей] = и + джей * 12;                          }                                               и = (джей << 2) & 4;                               джей++;                                        }                                               делай {                                             джей--;                                        } пока (джей > 0)                              } лови (e) {                                        alert("Крах: " + e.message);             } затем {                                           обнулить(a, и);                                }                                           }                                           }              

В целях рекламы, это пока единственный модуль, который позволяет вам сделать

лови (крах) {   КрахДетектор(крах); }

В целом, придумывать альтернативы ключевым словам — безумно интересно. Если придумаете что-то крутое — оставьте пожалуйста в комментариях. Всем хороших выходных и много-много, бесконечно много удовольствия от того что вы делаете 🙂

ссылка на оригинал статьи https://habrahabr.ru/post/283108/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *