Переднему концу необходимо изучить принцип компиляции в правильной позе (Часть 1)

внешний интерфейс JavaScript Язык программирования

предисловие

В последнее время на моем таймлайне было много статей типа "Зачем фронтенду изучать принцип компиляции" и "Как выучить AST во фронтенде", но я обнаружил, что никто не ввел как фронтенд конец должен быть систематически и правильно реализован.Изучите принципы компиляции, поэтому я поделюсь с вами своим опытом и опытом, основанным на моем собственном опыте и окольных путях, которые я сделал, надеясь, что все будут делать меньше обходных путей.

В конце концов, я не фронтенд, я просто умею писать на JavaScript.


содержание

Предыдущий:

  • Почему сложно составить
  • Как изучать языки программирования
  • какой именно код
  • Регулярная и контекстно-свободная грамматика
  • Языки программирования официально начались с AST

Следующий:

  • статический анализ
  • тип вычет
  • Трансформация АСТ
  • Conitnuation
  • виртуальная машина с байт-кодом

Почему сложно составить

Когда все упоминают принцип компиляции, первая реакция - это сложно, и трудно начать, но почему сложно? Грубо говоря, не является ли принцип компиляции технологией парсинга и преобразования одного языка в другой? Где именно эта технология мешает? Я думаю, что самым большим препятствием для этого является сам «язык программирования».

Я считаю, что друзья, которые читают эту статью, по крайней мере, изучили JavaScript, но я хочу спросить еще одну вещь: вы действительно понимаете JavaScript? Можете ли вы описать правила синтаксиса JavaScript? Можете ли вы понять логическую структуру, к которой относится грамматика? Знаете, как интерпретируется и выполняется JavaScript? Итак, вы действительно понимаете JavaScript? В любом случае, я все еще не могу с уверенностью сказать, что я «искусен» в JavaScript, потому что я до сих пор не знаю, как реализовать JIT.

В большинстве случаев, когда мы называем себя «знатоками» определенного языка программирования, это означает только то, что мы умеем пользоваться определенным языком программирования, но ядром предмета принципов компиляции является именно язык программирования, который требует от нас иметь глубокое понимание языка программирования и понимать, как он устроен и интерпретируется. Если у нас нет этой основы, очень трудно хорошо изучить этот предмет.

Рекомендуемое чтение:


Как выучить язык программирования чисел

Некоторые компьютерщики в зарубежных университетах любят для начала использовать Scheme с кафедры Лиспа Я сначала не понимал причины, пока не обнаружил, что их курсовая работа всегда требует в конце реализации простого интерпретатора Лиспа. Уровень организации учебных программ в зарубежных школах просто блестящий: школы учат Scheme не для того, чтобы дать ученикам писать инженерный код, а чтобы дать ученикам возможность изучить программирование и то, что такое сам язык программирования.

Лисп — это почти минимальная реализация возможностей современного языка программирования, а все языки программирования, являющиеся диалектом Лиспа, — это действительно больше, чем шутка. Сложность интерпретации простого Лиспа очень низка.Синтаксический анализ грамматики Лиспа так же сложен, как и разбор JSON.Мы часто видим, что многие новички могут реализовать интерпретатор Лиспа с сотнями строк кода. Хотя реализовать интерпретатор Лиспа несложно, он очень важен для студентов, он может дать студентам очень базовое, но очень всестороннее понимание построения и выполнения языков программирования и программ. И это всестороннее понимание языков программирования — это именно то, что мы имеем с C/C или JavaScript. То, чего всем не хватает для начала.

Так как же хорошо выучить язык программирования? Конечно, правильно закусывать нашу классическую божественную книгу "SICP", но учитывая серьезные хрестоматийные свойства "SICP", лекция получается не яркой и интересной, поэтому я бы рекомендовал книгу с более сильным научно-популярным характером, под названием «Расчет» «Сущность», вы можете использовать эту книгу, чтобы начать работу в первую очередь, и если у вас есть лишняя энергия или вы очень заинтересованы в обучении, вы можете перейти к «SICP».

Рекомендуемое чтение:


какой именно код

В предыдущем разделе мы упоминали, что сложность синтаксического анализа Lisp такая же, как и у JSON, поэтому можем ли мы просто использовать JSON вместо кода? Конечно, проанализированное синтаксическое дерево JavaScript представлено в формате JSON. Так что с точки зрения выразительности нет никакой разницы между кодом JavaScript и JSON. Итак, вопрос в том, какой именно код?

По сути, код, как и JSON, представляет собой структурированный текстовый формат данных. Здесь мы сосредоточимся только на двух функциях — «текст» и «структура».

Первой особенностью кода является текст, что означает, что все наши операции, такие как объединение, перехват или замена строк, могут быть применены к коду. Хотя многие программисты могут хорошо читать и писать все виды текста, но, похоже, не все понимают, что файл кода также может быть одним из файлов, которые можно читать, записывать и изменять.

Чтение, запись и манипулирование файлами кода - это первый важный порог для входа в мир компиляции. Иногда не требуются слишком сложные алгоритмы для выполнения каких-то значимых преобразований в коде. Например, мы можем напрямую анализировать импорт / экспорт с помощью обычного анализа. / требуют реализации простого вебпака, например, в моей предыдущей статье код хвостовой рекурсии был оптимизирован простой регуляризацией. После действительно сознательного обращения с файлом кода как с текстовым файлом мы можем извлечь код из «алтаря», позволяя каждому думать о коде, как если бы это был текст.

Второй характеристикой кода является структура. Я не знаю, сможете ли вы понять. За исключением литералов, другие части кода предназначены только для идентификации структуры и не имеют практического значения. Значение, придаваемое этим структурам, заключается в том, как интерпретатор выполняет этот код. Эта функция требует, чтобы мы формировали в уме структуру, когда смотрим на код, а не построчную строку.

var a = 123 // 除了字面量 123 外其他所有字符都是标识结构

For example, in the simple JavaScript code above, var is an abstract symbol, whether it is var or val, even if it is #%$, there is no problem, the only purpose is to identify this structure (statement) as a declaration Назначение.变量名 a 标识的是一种联系,这个 a 具体是什么也是无关紧要的,只要它所标识的联系不变,a 也是可以替换成任何字符。这里面唯一有实际意义的就是那个 123,我不能把它换成 456。

Перед Zhihu был вопрос, почему некоторые большие парни могут выучить язык программирования за две недели, и я ответил, что нам достаточно двух недель, чтобы создать язык программирования, такой же, как JavaScript.Брэндон АйкБольшой парень потратил неделю на его проектирование. Хотя я определенно не так хорош, как эти большие ребята, но дайте мне получить его в течение двух недель C fuck Не так уж и сложно создать JavaScript 1.0. Так что если перед статьей прочитать рекомендуемые книги и наверстать азы, то на самом деле каждый может легко выучить язык программирования за две недели.

И последнее, но не менее важное: то, что вы можете выучить язык программирования за две недели, не означает, что вы можете изучить область за две недели. Так же, как нельзя сказать, что изучение JavaScript приравнивается к изучению интерфейса, и нельзя сказать, что изучение Python приравнивается к изучению искусственного интеллекта (хотя многие учебные классы сейчас преподают основы Python под лозунгом искусственного интеллекта). интеллект), языки программирования - это всего лишь языки программирования. , это всего лишь инструмент.

Рекомендуемое чтение:

  • 《尾递归为啥能优化? 》- статья, которую я написал, Использование простой обработки символов для оптимизации хвостовых рекурсивных функций в циклы

Рекомендуемые инструменты:

  • AST Explorer—— Посмотрите, как выглядит JavaScript, который вы часто пишете

Регулярная и контекстно-свободная грамматика

Эта статья является уже четвертым разделом здесь, но только здесь мы можем официально взять наши классические учебники — «Книгу дракона», «Книгу тигра» или «Книгу кита» для изучения. В этом разделе кратко представлена ​​внешняя технология компилятора — Parser.

Передняя часть компилятора делает одну вещь, анализируя структурированный текстовый файл кода в структуру данных, которую может понять наш компьютер — абстрактное синтаксическое дерево (AST). Парсинг кода — довольно скучный, сложный и утомительный процесс. Эта сложность и громоздкость обусловлены громоздким и сложным синтаксическим дизайном самого языка программирования. Например, Лисп, который мы обсуждали ранее, очень легко анализируется благодаря его очень простой, последовательной и однозначной грамматике, но ценой множества разглагольствованных скобок Лиспа.

Код синтаксического анализа обычно делится на два этапа.Первый этап — это лексический анализ, который преобразует код текста в токены. Ввиду того, что все здесь должны иметь некоторые основы регулярных выражений, в процессе разбора кода нам нужно использовать регулярные выражения для сегментации слов для лексического анализа. С точки зрения принципов компиляции, когда мы изучаем регулярные выражения, мы изучаем не только регулярные выражения, но и обычный DFA ядра, но эта часть не слишком сложна.

Вторым шагом в анализе кода является синтаксический анализ, который преобразует токен, который мы лексически проанализировали выше, в AST. Анализ грамматики Мы должны изучить контекстно-свободную грамматику (CFG), которая может быть представлена ​​BNF. CFG более мощный, чем регулярное выражение.Он сильнее в том, что CFG может выражать рекурсивные структуры.Обычные рекурсивные структуры включают выражения и блоки кода. В части синтаксического анализа достаточно базового алгоритма LL(1) и достаточного понимания нисходящего анализа.

Будь то регулярный или CFG, все они используют формальный язык (наш язык программирования также является формальным языком) для описания абстрактной структуры, поэтому в процессе обучения вы должны иметь эту абстрактную структуру в своем уме. больше с меньшими затратами.

Парсер — сложный пункт в принципе компиляции, но не суть, поэтому в этой части все считают, что сложный алгоритм можно вообще пропустить, и не рекомендуется тратить слишком много времени. Парсер может быть сгенерирован автоматически в соответствии с обычным и CFG, и его не нужно писать вручную. Таким образом, основная цель этой части — изучить регулярность и CFG, и эти сложные алгоритмы не имеют большого значения.

Наконец, есть очень интересное явление: регулярные выражения — это контекстно-свободные грамматики, а БНФ — регулярные грамматики, можно подумать, почему?

Рекомендуемое чтение:

  • Непонимание парсера- Моя собственная статья о том, как начать
  • Выберите из Книги Дракона, Книги Тигра или Книги Кита - Классический учебник классических принципов компиляции
  • Я конечно шучу—— Блог Иньшеня, пожалуйста, автоматически блокируйте субъективное самоисцеление Иньшеня при чтении

Рекомендуемые инструменты:

  • Acorn- Парсер JavaScript
  • REGEXPER- Отображение регулярных выражений в графическом виде
  • Ohm- Визуальный редактор БНФ
  • Jison- Создание универсального парсера с регуляризацией и BNF

Языки программирования официально начались с AST

На самом деле принцип компиляции в большинстве случаев остается на стадии парсера, потому что большинство людей застревают на этой стадии, когда они учатся. Но на самом деле Parser — это лишь самый поверхностный слой технологии в этой области. Язык программирования начинается с AST.Только на этапе AST наш компьютер может анализировать, интерпретировать или переводить наш язык программирования, и код, который мы так усердно написали перед нами, только для нас Это все для этих глупых людей .

Анализ, преобразование, интерпретация и перевод языка программирования AST должны быть наиболее важной частью принципа компиляции, но поскольку наша классическая книга по принципам компиляции была опубликована относительно рано (1985 г.) и сосредоточена только на популярном языке C, она в основном скомпилированный язык, поэтому его внимание сосредоточено на анализе кода и создании сборки. Но с точки зрения современных языков программирования, во внешнем интерфейсе есть Parser Generator, а во внутреннем — LLVM, поэтому нам следует больше сосредоточиться на среднем конце.

Но на данный момент контента, который мы представили, на самом деле достаточно для большинства мелких партнеров, чтобы написать DSL для себя и написать небольшой язык, скомпилированный в JavaScript, для себя, чтобы играть. Но достаточно ли этого? Что именно мы можем сделать с AST? Увидимся в следующий раз.

Справочный проект:

  • bramblex/blx-fsm- Мой собственный игрушечный DSL для описания FSM
  • bramblex/Smooth- мой собственный игрушечный язык

Hello World!