Хаохао — фронтенд-инженер, он недавно начал работать в области инженерии и хочет получить некоторые знания о компиляции. Так получилось, что я учился раньше него, поэтому представил ему то, что знал, поэтому был следующий диалог.
Что такое компиляция?
昊 昊: Недавно я хотел бы узнать кое-что о компиляции Брат Гуанг, что такое компиляция?
я: Компиляция — это технология преобразования, с одного языка программирования на другой, с языка высокого уровня на язык низкого уровня или с языка высокого уровня на язык высокого уровня, такая технология преобразования.
Хао Хао: Что такое язык высокого уровня и что такое язык низкого уровня?
я:低级语言
Это связано с машиной, включая регистры, инструкции процессора и т. Д., Особенно «низкие», описывающие процесс выполнения, специфичный для машины, такой как машинный язык, язык ассемблера, байт-код и т. Д.高级语言
Нет такой вещи, как конкретное выполнение, оно в основном используется для выражения логики и предоставляет условия, циклы, функции, объектно-ориентированные и другие функции для организации логики, а затем компилируется для автоматического преобразования этой описанной высокоуровневой языковой логики в низкоуровневую. инструкции языка уровня, которые могут удобно выражать логику, не влияя на конкретное выполнение. Неправильно говорить, что это не влияет на выполнение, потому что, если вы пишете напрямую на ассемблере, вы можете написать наиболее эффективный код, но если язык высокого уровня автоматически преобразуется в язык низкого уровня посредством компиляции, это трудно обеспечить эффективность выполнения сгенерированного кода.Этот вид оптимизации компиляции представляет собой трудность в области компиляции.
На самом деле, вдумайтесь, мы конвертируем идеи в уме и сформулированные решения в языковые коды высокого уровня.Этот процесс тоже конвертация?Можно ли его автоматизировать?В этом задействован ИИ. Теперь есть направление исследований интеллектуальных технологий для понимания кода генерации документов требований.
Хао Хао: Как именно конвертируется?
я: Чтобы преобразовать первое, чтобы понять две стороны преобразования, что собирается преобразовать, что преобразуется в? Например, язык высокого уровня к расширенному языку, преобразовать строку, организую в соответствии с определенными форматами, форматы называются Lexics, синтаксисом, целым, называемым грамматикой, цель преобразования, если цель также Язык высокого уровня, то вы должны понимать формат целевого языка, если цель - это низкоуровневый язык, такой как компиляция, то вам нужно все знать. Тогда вы должны выполнить преобразование семантической эквивалентности, обратите внимание на это“语义等价”
, Интерпретируя другой язык через один язык, нельзя терять или добавлять какую-то семантику, она должна быть последовательной.
Зная, каковы две стороны преобразования, вы можете выполнить преобразование.Во-первых, дайте компьютеру понять, что нужно преобразовать.Что это такое?“计算机理解“
Шерстяная ткань? Это чтобы сообщить компьютеру лексические и грамматические форматы, которые мы задаем.Как это сказать? Это структура данных.Компьютер может обрабатывать результат анализа строки исходного кода в соответствии с определенной структурой данных. Этот процесс называется разбором, который требует сегментации слов перед построением синтаксического дерева.
На самом деле нужно «понять» не только поле компиляции, но и много других полей, которые нужно «понять»:
Механизм полнотекстового поиска также должен сначала сегментировать искомые строки с помощью токенизатора, а затем искать эти слова в базе данных, которая сегментируется и индексируется тем же токенизатором, и оценивает и сортирует совпадающие результаты слов, которые полнотекстовый поиск.
Область искусственного интеллекта должна иметь дело с естественным языком, и он также должен «понимать» по лексике, грамматике, синтаксису и т. д., и после того, как он становится определенной структурой данных, компьютер может только понять и обработать его, и затем задействуются различные алгоритмы обработки.
Сегментация слова делится в соответствии с конечным автоматом (有限状态机 DFA
), для чего это, зачем это нужно для сегментации слов, я знаю, у вас должны быть сомнения. Поскольку лексическое описание представляет собой формат наименьшего слова, например, идентификатор не может начинаться с цифры, за которой следует буквенно-цифровое подчеркивание и т. д. В этом случае также есть ключевые слова if, while, continue и т. д., которые не могут быть далее подразделены, и тогда более тонкие Пункты не имеют смысла. Сегментация слов состоит в том, чтобы превратить строку в наименьшую единицу слов, которую нельзя разделить снова, также называемую токеном, поскольку разные форматы слов разные, вы не можете писать, если еще иметь дело с разными форматами. На самом деле, это действительно нормально, вэньян, если еще, жалуйтесь на это. Но когда 100 слов в формате для обработки, все пишутся как бы иначе, боже мой, неужели код еще видно? Таким образом, процесс обработки каждого слова следует рассматривать как состояние. При обработке другого формата слова происходит переход в другое состояние. Способ перехода, естественно, зависит от обрабатываемого в данный момент символа. Обработка строки происходит из начальное состояние в текущее состояние.Для обработки используются разные состояния, которые являются автоматом состояний.После того, как каждый токен распознан, его можно выкинуть, а конечным выходом будет массив токенов.
На самом деле состояние находится не только на первом уровне.Если вы думаете о начальном теге html-тега, его можно обрабатывать как состояние, но это состояние также необходимо для обработки атрибутов, начальных тегов и т. д. Это состояние второго уровня, и атрибуты могут быть дополнительно уточнены.Оно разделено на несколько состояний, с которыми нужно иметь дело.Это трехуровневое состояние.Это идея разделяй и властвуй, и она обрабатывается слой за слоем.
После сегментации слов мы получаем слова одно за другим, а затем нам нужно собрать эти слова, чтобы сгенерировать ast Почему должен ast? Я знаю, вы должны захотеть спросить. На самом деле коды высокоуровневых языков все вложенные.Если посмотреть на низкоуровневые языки, такие как ассемблер, то это линейная структура.Однако в высокоуровневых языках есть различные блоки типа функций , if, else, while и т. д. вложенные. Следовательно, естественно организовать древовидную структуру данных для понимания компьютером, т.Abtract Syntaxt Tree
, синтаксическое дерево и абстракция, то есть игнорирование некоторых бессмысленных разделителей, таких как , и другие символы в html, { }() [] в js; это детали, не обращайте внимания, комментарии Также он будет проигнорирован, комментарии будут разделены только по словам, но не будут помещены в ast.
Как собрать, или вложенная сборка, это значит рекурсивная сборка?Да, вы правы, требуется рекурсия, не только аст сборка здесь требует рекурсии, но и очень много рекурсии в последующей обработке, если только это не линейный код. Стадии, как и сборка, рекурсивны, а не вложенные структуры могут быть рекурсивными.
Мы только что проанализировали лексический формат, то есть строковый формат, один за другим, а грамматику — это ассемблерный формат, представляющий собой комбинацию слов. Вот почему мы должны сначала разбить слова. Если мы собираем ast непосредственно из строк, мы будем иметь дело со строковым уровнем, а начиная с токена - это уровень слов. Это все равно, что позволить вам построить замок из блоков, но блоки также Если вы хотите построить его самостоятельно, как вы его строите?Вы можете построить строительные блоки один за другим, а затем собрать их в замок, или вы можете собирать во время строительства строительных блоков. Однако, в случае с маленькой машиной, вы можете делать строительные блоки и собирать их одновременно На уровне замка вы можете делать строительные блоки и собирать их одновременно Сможете ли вы выяснить, какие строительные блоки строить Это сложно, так что это зависит от ситуации. Есть два способа сделать синтаксический анализатор, простой лексический анализ можно использовать для анализа горячих слов, а затем сразу же собирать их в ast, такие как html и css, но как js и c++, если вы сначала не причастие, начиная непосредственно с строку для создания ast, могу только сказать, что она слишком жестокая.
说了半天积木和组装,那么怎么组装呢,从左到右的处理token,遇到一个token怎么知道他是啥语法呢,这就像怎么知道一块积木是属于那个部件的。 There are also two kinds of ideas, one is that you first determine this building block belonging to that component, then find the drawings of that component, assemble it according to the drawings, the other is you first assembled, and then look at this is отдельно.这就是两种方式,先根据一两个积木确定是哪个部件,再按照图纸组装这个部件,这种是ll
Кстати, сначала собери, после сборки посмотри какие детали, этоlr
Путь. Метод ll состоит в том, чтобы определить, какие узлы ast собраны. Вам нужно просмотреть несколько узлов ast. В зависимости от того, сколько посмотреть, чтобы определить, что собрано, вы будете LL (1), LL (2) и другие алгоритмы. ll — это рекурсивный спуск, который является самым простым способом ассемблирования.Конечно, некоторые люди думают, что путь lr тоже достаточно прост. ll Есть проблема, которую надо решить с помощью lr, то есть рекурсивный спуск сталкивается с ситуацией, когда левая часть рекурсивно идет до конца. по чертежам можно сначала собрать а потом смотреть что собрано. Это на самом деле очень похоже на жизнь: один из способов — посмотреть вниз на две ступеньки и решить, как идти сейчас. На самом деле я принадлежу ко второму типу, планирования нет.
После лексико-грамматического анализа генерируется аст. Для описания исходного кода используется древовидная структура данных, которая становится понятной компьютеру и может быть позже интерпретирована, выполнена, скомпилирована и преобразована. Будь то интерпретация или компиляция, его нужно сначала разобрать, то есть дать компьютеру понять, что это такое, а потом решить, как с этим быть.
Позже преобразуйте древовидный ast в другой ast, а затем распечатайте его как строку целевого кода.Это транслятор, который интерпретирует и выполняет ast или интерпретирует и выполняет линейный промежуточный код.Это интерпретатор, который преобразует ast в линейный промежуточный код, затем генерирует код сборки, затем выполняет сборку и компоновку, генерирует машинный код, это компилятор.
Как компилятор обрабатывает AST?
Хао Хао: Брат Гуанг, как компилятор обрабатывает ast?
я: С ast компьютер может понимать высокоуровневый код языка, но компилятору нужно генерировать низкоуровневый код, например ассемблерный код, который далек от ast. Поскольку один является вложенным и древовидным, а другой линейным и последовательным, так что вам нужно сначала преобразовать его в линейный код, а затем сгенерировать низкоуровневый код. Я думаю, что аст тоже можно рассматривать как разновидность дерева ИР,IR
Это смысл промежуточного представления непосредственного представления. Сначала преобразуйте AST в линейный IR, а затем сгенерируйте сборку, байт-код и т. д.
Как перевести, как древовидная структура становится линейной? Очевидно рекурсивный, рекурсивный AST по грамматической структуре, переводит каждый узел, это называется переводом, управляемым грамматикой, и использует инструкции линейного IR для перевода атрибутов узла AST. Для метода перевода каждого узла, если перевод, во время перевода и т. д., вы можете перейти к соответствующей информации и выполнить поиск промежуточной генерации кода.
Но ast не может подойти и обратиться к промежуточному коду.
Хао Хао: Почему нельзя ast представить информацию об исходном коде, почему ее нельзя напрямую перевести в линейный ir?
я: Поскольку семантическая проверка не была проведена, структура не обязательно имеет правильное значение, например, «Хаохао — свинья», это грамматически, но семантика явно неверна, разве это не проклятие, поэтому вы должны сделать сначала семантическая проверка. Кроме того, перед последующим переводом необходимо получить некоторую информацию.
Семантический анализ должен проверять наличие семантических ошибок, таких как совпадение типов, существование ссылочной переменной, наличие разрыва во время и т. д., в основном для выполнения作用域分析
,引用消解
,类型推导和检查
,正确性检查
Ждать.
Анализ области видимости заключается в анализе функций, блоков и т. д., какие переменные находятся в этих областях видимости, и какая связь между областями действия?По сути, область видимости — это дерево, а дерево можно сгенерировать из области видимости верхнего уровня. к структуре данных подобласти. Я помню плагин webpack для анализа области видимости, он также связывал модули, чтобы сформировать большой граф области видимости, а затем анализировал его.
В области действия находятся различные объявления, и должны быть записаны их типы, начальные значения, модификаторы доступа и другая информация.Структура, сохраняющая эту информацию, называется таблицей символов, что эквивалентно кешу.При обработке этого символа проверяйте символ напрямую.Таблица в порядке, не нужно искать ее снова с аста.
Справочное разрешение заключается в проверке того, можно ли найти определение для каждого символа, и сообщении об ошибке, если оно не может быть найдено. Вы относительно знакомы с типом.Прописать тип в исходном коде js однозначно невозможно.Его можно напрямую вывести во многих местах.Согласно асту объявление типа можно получить и записать в таблицу символов. Введите для проверки, в случае несоответствия будет сообщено об ошибке. Есть и другие тривиальные проверки, такие как continue, break может появиться только через while и так далее.
Хао Хао: Я понимаю семантический анализ, который заключается в проверке ошибок и записи некоторой проанализированной информации в таблицу символов, а что после семантического анализа?
После семантического анализа это означает, что в программе нет грамматических и смысловых ошибок, и различные последующие преобразования можно выполнять с уверенностью, и ошибок разработчика больше не будет. После этого он сначала транслируется в линейный ИР, а затем оптимизируется линейный ИР.Оптимизация необходима, потому что автоматически сгенерированный код неизбежно имеет много избыточности, и нужно убрать различные ненужные обработки. Но оставьте семантику неизменной. Например, удаление мертвого кода, удаление общих подвыражений, распространение констант и т. д.
Анализ линейного IR требует создания графа потока, который является графом потока управления.控制流
Он основан на переходах программы, вызванных if, while, вызовами функций и т. д. Связь между последовательно исполняемым кодом и кодом с переходом представляет собой граф, а последовательно исполняемый код рассматривается как единое целое, которое называется базовым быстрым. Затем проведите анализ потока данных на основе этого графа потока, то есть проанализируйте код, через который проходит переменная, а затем на их основе выполните различные оптимизации.
Эта часть называется анализом программы или静态分析
, это особое направление, которое можно использовать для статической проверки уязвимостей кода, а можно использовать для оптимизации компиляции, что относительно сложно. Есть очень мало докторов наук, занимающихся исследованиями в этой области. В Китае только Пекинский университет и Нанкинский университет предлагают курсы анализа программ.
Оптимизированная линейная ИР может генерировать ассемблерный код, а затем преобразовывать его в машинный код через ассемблер, а затем линковать некоторые стандартные библиотеки.Например, вы можете увидеть директорию встроенных инструментов в директории v8.Здесь находятся различные скомпилированные файлы машинного кода, которые может быть статически связан с исполняемым файлом.
Хао Хао: О, я чувствую, что интерфейс двух шагов компиляции и компоновки нельзя трогать.
я: Да, потому что js — это интерпретируемый язык, он интерпретируется и выполняется прямо из исходного кода, не говоря уже о js, а байт-код java не нуждается в статической линковке. Только те, кто генерирует исполняемые файлы, такие как C и C++, должны преобразовать код в машинный код через ассемблер, а затем связать его в файл. И если на целевой платформе есть эти библиотеки, их не нужно статически связывать друг с другом, их можно связывать динамически. Возможно, вы слышали о .dll и .so, которые представляют собой файлы Windows и linux, содержащие машинный код для динамической загрузки во время выполнения соответственно.
Вы правы, front-end поле в принципе не нуждается в сборке и линковке, даже wasm генерирует wasm байткод, а потом его интерпретирует и выполняет. Фронтенд в основном переводчик.
Как транспилятор обрабатывает AST?
Хао Хао: Что делает переводчик после ast?
я: Целевой код транслятора также является языком высокого уровня и вложенной структурой, поэтому от языка высокого уровня к языку высокого уровня это от древовидной структуры к древовидной структуре Линейный ИК, высокоуровневый для высокоуровневого преобразования языка требуется только ast, после выполнения различных преобразований на ast можно выполнять генерацию кода.
Хао Хао: Я сказал, что не слышал о концепции линейного IR в Babel.
я: Да, будь то кросс-языковая конвертация, типа ts в rust, или та же языковая конвертация из js в js, никакой линейной структуры не требуется.Какой линейный промежуточный код требуется для конвертации двух деревьев. Итак, общий переводчикparse
,transform
,generate
эти 3 этапа.
В широком смысле синтаксический анализ включает в себя лексический, грамматический и семантический анализ, а синтаксический анализ в узком смысле относится к грамматическому анализу. Это не следует путать.
Преобразование — это добавление, удаление и изменение аста, а затем генератор печатает аст в виде строки.При разборе аста мы удаляем разделители, такие как []{}(), а затем добавляем детали обратно при генерации.
На самом деле фронтенд-поле — это в основном переводчик, потому что основной движок js выполняет исходный код, но исходный код не совпадает с исходным кодом, который мы написали, поэтому многие фронтенд-трансляторы исходного кода делают это преобразование, такое как babel, typescript, terser, eslint, postcss, prettier и т. д.
Babel преобразует es-код старшей версии в младшую версию и внедряет полифилл. Typescript — это проверка типов и преобразование в код js. eslint проверяется на соответствие спецификации, но --fix также может генерировать фиксированный код. Prettier также используется для форматирования кода, который обрабатывает больше, чем eslint, а не только js. postcss в основном работает с css, а posthtml используется для работы с html. Я считаю, что вы использовали его много. Небольшой программный переводчик, такой как taro, упакован на основе babel.
Как интерпретатор обрабатывает AST?
Хао Хао: О, брат Гуанг, я, наверное, знаю, что компилятор и интерпретатор сделали с ast. Оба они генерируют код. А интерпретатор?
я: Да, во-первых, транслятор тоже своего рода компилятор, но он особенный, называетсяtranspiler
, общий компилятор называетсяcompiler
. Разница между интерпретатором и компилятором действительно заключается в том, генерировать ли код, а тот, который заранее скомпилирован в машинный код, называетсяAOT
Компилятор, который компилирует в машинный код во время выполнения, называетсяJIT
перевод
Интерпретатор не генерирует машинный код, тогда как его реализовать? Вы знаете, должны быть сомнения.
Фактически, интерпретатор использует один язык высокого уровня для интерпретации другого языка высокого уровня, такого как C++.Как правило, C++ используется для написания интерпретатора, поскольку он может управлять памятью. Используйте c++ для написания интерпретаторов js, таких как v8, spidermonkey и т. д. После того, как у нас есть ast и завершен семантический анализ, мы можем пройти ast, а затем использовать C++ для выполнения различных узлов.Это называется интерпретатором обхода дерева, который напрямую интерпретирует и выполняет ast.Движок v8 делал это до 17 лет. . . . Но через 17 лет был введен байт-код, потому что байт-код можно кэшировать, поэтому в следующий раз, когда вы будете выполнять байт-код напрямую, вам не нужно его анализировать. Байт-код представляет собой линейную структуру, также требуется преобразование из ast в linear ir, а затем байт-код выполняется на vm.
Как правило, программы, которые интерпретируют линейный код, такой как ассемблерный код, байтовый код и т. д., называются虚拟机
, потому что машинный код линейный, на самом деле его можно объяснить из ast, но он не называется vm.Я думаю, именно из-за этого интерпретатор линейного кода, который похож на машинный код, называется vm.
Будь то интерпретация ast или преобразование его в байт-код и последующая интерпретация, эффективность не будет особенно высокой, потому что для выполнения кода текущего языка используются другие языки высокого уровня, поэтому для повышения эффективности он по-прежнему необходимо компилировать его в машинный код. Этот вид компиляции во время выполнения является JIT-компилятором. Компиляция занимает много времени, поэтому не весь код является JIT. Необходимо считать тепло, и JIT будет выполнен, когда порог достигнут. Затем кешируйте машинный код, конечно, это может быть кешированный ассемблерный код, и используйте ассемблер для преобразования его в машинный код, когда он используется, потому что машинный код занимает много места.
Это можно понять, сравнив v8, v8 имеет парсер, интерпретатор зажигания, турбовентиляторный компилятор и gc.
ignation
Интерпретатор преобразует разобранный ast в байт-код, а затем интерпретирует и выполняет байт-код.После того, как тепло достигнет порога, он будет передан турбовентилятору для компиляции в ассемблерный код, а затем сгенерирует машинный код для ускорения. GC независим в управлении памятью.
turbofan
Это турбокомпрессор, и название отражает значение JIT. Однако JIT улучшает скорость выполнения, но также имеет недостатки. Например, он сделает js-движок больше и займет больше памяти. Поэтому облегченный js-движок не включает jit. Это компромисс между скоростью выполнения, пакетом размер и объем памяти. Архитектурный дизайн также часто делается с обеих сторон, но чтобы выбрать компромисс, мы называем это смешиванием планов.
Говоря о компромиссах, я помню, что js-движок rn's hermes был изменен для поддержки прямого выполнения байт-кодов.Во время компиляции js-код компилируется в байт-коды, а затем байт-коды выполняются напрямую.Это js-движок в кросс-энде. поле.
Где используются знания компиляции в области переднего плана?
Хао Хао: О, брат Гуанг, я понимаю, что делают интерпретаторы, компиляторы и трансляторы, в каких местах во фронтенде используются знания о принципах компиляции?
я: Вообще-то у вас должно быть общее представление, но оно недостаточно ясное, я перечислю то, что знаю.
工程化领域各种转译器
: babel, typescript, eslint, terser, prettier, postcss, posthtml, таро, компилятор шаблонов vue и т. д.
js引擎
: v8, javascriptcore, quickjs, hermes и т. д.
wasm
: llvm может генерировать байт-код wasm, поэтому C++, rust и другие языки, которые можно преобразовать в llvm ir, можно использовать для разработки wasm.
ide 的 lsp
: Подсветка синтаксиса, интеллектуальные подсказки, проверка ошибок и т. д. языка программирования взаимодействуют через протокол языковой службы, в то время как сервер lsp в основном анализирует редактируемый текст на основе синтаксического анализатора.
Как реализовать язык самостоятельно?
Хао Хао: Могу ли я реализовать язык после того, как изучу принцип компиляции?
я: На самом деле, язык программирования в основном проектируется.Если он будет реализован, то сначала будет реализован парсер и семантический анализ, а затем он будет разделен на два пути.Один - это интерпретация выполнения интерпретатора с помощью JIT-компилятора, а другой - скомпилировать его в ассемблерный код, а затем сгенерировать. Затем машинный код связывается компилятором с исполняемым файлом.
Часть парсера громоздка, вы можете использоватьantlr
Генерируется такой генератор парсеров, а семантический анализ надо писать самому, это не слишком сложно, в основном для различной обработки ast. Позже, если вы захотите сделать компилятор, вы можете использоватьllvm
Этот оптимизатор общего назначения и генератор кода, clang, rust и swift основаны на нем, поэтому он очень надежен и может использоваться напрямую. Если вы интерпретатор, вы можете написать интерпретатор обхода дерева или дополнительно сгенерировать линейный байт-код, а затем написать виртуальную машину для интерпретации байт-кода. Компилятор JIT также может сделать это с помощью llvm. Преобразование ast в llvm ir также представляет собой древовидную структуру в линейную структуру, что является очень распространенной операцией в области компиляции.
На самом деле, принцип компиляции просто говорит вам, как его реализовать. Дизайн языка не заботится о реализации. Язык может быть реализован как скомпилированный тип или как интерпретируемый тип. Его также можно превратить в java, который компилируется, а затем интерпретирует.Вы можете видеть, что hermes (реагировать на нативную реализацию).js engine) заключается не в том, чтобы сначала скомпилировать js в байт-код, а затем интерпретировать и выполнить байт-код. Языки не делятся на компиляцию и интерпретацию.Это понятие необходимо использовать.Си тоже имеет интерпретатор, а js тоже компилятор.Когда мы говорим что язык компилируется или интерпретируется,это в основном определяется мейнстримным способом компиляция или интерпретация.
Языки программирования можно разделить наGPL
а такжеDSL
два вида.
GPL — это язык программирования общего назначения, полный по Тьюрингу, то есть может описать любую вычислимую задачу, такие языки, как c++, java, python, go, rust и т. д., полны по Тьюрингу, поэтому язык может достичь другого языка. Язык может быть реализован, но сложность реализации отличается. Например, язык go имеет встроенную реализацию сопрограмм, поэтому легко писать программы с высокой степенью параллелизма, а в Java нет сопрограмм на уровне языка, поэтому их необходимо реализовывать на верхнем уровне. Возможно, вы слышали, что шаблоны проектирования являются дополнением к недостаткам языка.Разные языки имеют разные дизайнерские идеи и разные встроенные функции.Иногда их нужно компенсировать средой выполнения. ,
Языки программирования имеют разные дизайнерские идеи, и общее направление — это парадигмы программирования, такие как императивная, декларативная, функциональная, логическая и т. д. Эти основные идеи приведут к синтаксису языка, встроенные реализации разные, и возможности выражений тоже разные. разные. Это в основном определяет тон языка, и его сложно потом дополнить.Так же, как функциональный стиль в js, вы не можете запретить другим использовать императивный стиль, поэтому сложно писать чистый функциональный код.
DSL не является полным по Тьюрингу, но в обмен на более сильную выразительность в определенной области, такой как html, css, регулярные выражения, синтаксис селектора jq и т. д., он больше похож на псевдокод и обладает сильной выразительной способностью в конкретных областях. fields , но он не является полным по Тьюрингу и не может описать все вычислимые проблемы.
Принцип компиляции заключается в том, чтобы изучить шаги по реализации языка программирования, и есть много вещей, которые нужно изучить в разработке языка верхнего уровня.Лучше всего быть знакомым с характеристиками нескольких языков программирования.
Как я могу изучить принципы компиляции?
Хао Хао: Брат Гуанг, как мне узнать принцип компиляции?
я: Прежде всего, вам нужно понять, что вам нужно узнать о компиляции.Возможно, вы можете получить представление о моей научно-популярной компиляции, переводе и объяснении, а затем проверить соответствующую информацию. После того, как вы узнаете, что вы можете сделать, сначала напишите синтаксический анализатор, потому что, несмотря ни на что, вы должны сначала разобрать его в ast, прежде чем его можно будет «понять» и обработать позже.Изучите конечный автомат для сегментации слов и рекурсивного спуска для построения аст. Рекомендуется посмотреть парсер компилятора шаблонов vue.Этот парсер xml относительно прост и подходит для входа. Есть много деталей парсера на уровне языка, так что вам все равно придется найти один для отладки. Но я не думаю, что это нужно.Вообще, я просто пишу парсер html.Если это язык, то его может сгенерировать antlr. Транспайлер должен знать babel, который является очень хорошим транспилятором во фронтенде.
Движок js может попытаться использовать babel в качестве синтаксического анализатора, самостоятельно провести семантический анализ, попытаться интерпретировать и выполнить ast, а затем дополнительно сгенерировать байт-код или другой линейный ir, а затем написать виртуальную машину для интерпретации байт-кода.
Вы также можете изучить связанные с wasm технологии, которые включают в себя процесс компиляции других языков в байт-код wasm.
Я пишу буклет «Коды для очистки плагинов Babel», в котором будут реализованы интерпретатор js, транспайлер, проверка типов, линтер и т. д. Это требует большого знания принципов компиляции, которые могут помочь вам начать работу с принципами компиляции.
Когда вы изучили принципы компиляции, вы, вероятно, знаете, как реализовать язык программирования.Если вы хотите углубиться в разработку языка, вы можете изучить больше языков из других парадигм программирования, понять различные языковые функции и как проектировать очень выразительная gpl или dsl.
Вы также можете узнать больше об операционной системе и архитектуре, потому что скомпилированный код по-прежнему должен выполняться в виде процесса в операционной системе, поэтому для проектирования среды выполнения требуется понимание операционной системы. Тогда как набор инструкций процессора реализован с помощью схем?Если вы хотите углубиться, вы можете посмотреть на архитектуру компьютера.
Тем не менее, фронтенд-инженерам не нужно достигать такой глубины, но иметь более широкую перспективу не помешает.