Сравнивайте с английским: нажмите на абзац — оригинал откроется в окне. Кнопка EN под абзацем показывает его прямо в тексте.
Содержание
Введение
Преобразование компьютерного кода в машиночитаемую форму
Converting computer code into a machine readable form
В вычислительной технике генерация кода является частью цепочки процессов компилятора и преобразует промежуточное представление исходного кода в форму (например, машинный код), которую может непосредственно выполнить целевая система. Сложные компиляторы обычно выполняют несколько проходов по различным промежуточным представлениям. Этот многоэтапный процесс используется, поскольку многие алгоритмы оптимизации кода проще применять последовательно, либо потому, что входные данные для одной оптимизации зависят от завершенной обработки, выполненной другой оптимизацией. Такая организация также упрощает создание единого компилятора, способного работать с несколькими архитектурами, поскольку только последний этап генерации кода (бэкенд) необходимо изменять для каждой целевой платформы. (Более подробную информацию о разработке компиляторов можно найти в статье "Компилятор".) Входные данные для генератора кода обычно состоят из дерева разбора или абстрактного синтаксического дерева. Дерево преобразуется в линейную последовательность инструкций, как правило, на промежуточном языке, таком как трехадресный код. Дальнейшие этапы компиляции могут называться "генерацией кода" или не называться, в зависимости от того, связаны ли они со значительным изменением представления программы. (Например, оптимизация "заглядывание" вряд ли будет названа "генерацией кода", хотя генератор кода может включать в себя этап оптимизации "заглядывание".)
In computing, code generation is part of the process chain of a compiler and converts intermediate representation of source code into a form (e. g., machine code) that can be readily executed by the target system. Sophisticated compilers typically perform multiple passes over various intermediate forms. This multi stage process is used because many algorithms for code optimization are easier to apply one at a time, or because the input to one optimization relies on the completed processing performed by another optimization. This organization also facilitates the creation of a single compiler that can target multiple architectures, as only the last of the code generation stages (the backend) needs to change from target to target. (For more information on compiler design, see Compiler.) The input to the code generator typically consists of a parse tree or an abstract syntax tree. The tree is converted into a linear sequence of instructions, usually in an intermediate language such as three address code. Further stages of compilation may or may not be referred to as "code generation", depending on whether they involve a significant change in the representation of the program. (For example, a peephole optimization pass would not likely be called "code generation", although a code generator might incorporate a peephole optimization pass.)
Создание кода во время выполнения
Когда генерация кода происходит во время выполнения, как, например, при JIT-компиляции, важно, чтобы весь процесс был эффективен как по времени, так и по используемой памяти. Например, при интерпретации регулярных выражений и использовании их для генерации кода во время выполнения, часто создается недетерминированный конечный автомат вместо детерминированного, поскольку обычно первый можно создать быстрее и он занимает меньше памяти, чем второй. Несмотря на то, что JIT-генерация кода обычно приводит к менее эффективному коду, она может использовать информацию профилирования, доступную только во время выполнения.
When code generation occurs at runtime, as in just in time compilation (JIT), it is important that the entire process be efficient with respect to space and time. For example, when regular expressions are interpreted and used to generate code at runtime, a non deterministic finite state machine is often generated instead of a deterministic one, because usually the former can be created more quickly and occupies less memory space than the latter. Despite its generally generating less efficient code, JIT code generation can take advantage of profiling information that is available only at runtime.
Связанные понятия
Основная задача получения входных данных на одном языке и выдачи выходных данных на существенно отличающемся языке может быть понята в терминах основных преобразующих операций теории формальных языков. Следовательно, некоторые методы, изначально разработанные для компиляторов, стали применяться и в других областях. Например, YACC (Yet Another Compiler Compiler) принимает входные данные в форме Бэкуса — Наура и преобразует их в парсер на языке C. Хотя изначально он был создан для автоматической генерации парсера для компилятора, yacc также часто используется для автоматизации написания кода, который необходимо изменять при каждом изменении спецификаций. Многие интегрированные среды разработки (IDE) поддерживают ту или иную форму автоматической генерации исходного кода, часто используя алгоритмы, общие с генераторами кода компиляторов, хотя обычно менее сложные. (См. также: Преобразование программ, Преобразование данных.)
The fundamental task of taking input in one language and producing output in a non trivially different language can be understood in terms of the core transformational operations of formal language theory. Consequently, some techniques that were originally developed for use in compilers have come to be employed in other ways as well. For example, YACC (Yet Another Compiler Compiler) takes input in Backus–Naur form and converts it to a parser in C. Though it was originally created for automatic generation of a parser for a compiler, yacc is also often used to automate writing code that needs to be modified each time specifications are changed. Many integrated development environments (IDEs) support some form of automatic source code generation, often using algorithms in common with compiler code generators, although commonly less complicated. (See also: Program transformation, Data transformation.)
Отражение
В целом, синтаксический и семантический анализатор стремится получить структуру программы из исходного кода, а генератор кода использует эту структурную информацию (например, типы данных) для генерации кода. Иными словами, первый добавляет информацию, а второй часть информации теряет. Одним из последствий этой потери информации является то, что рефлексия становится затруднительной или даже невозможной. Чтобы решить эту проблему, генераторы кода часто внедряют синтаксическую и семантическую информацию, помимо кода, необходимого для исполнения.
In general, a syntax and semantic analyzer tries to retrieve the structure of the program from the source code, while a code generator uses this structural information (e. g., data types) to produce code. In other words, the former adds information while the latter loses some of the information. One consequence of this information loss is that reflection becomes difficult or even impossible. To counter this problem, code generators often embed syntactic and semantic information in addition to the code necessary for execution.