Компилятор пишется так


Содержание

[чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

не заморачивайся, ты физик, так думай о своей физике. зачем тебе полжизни тратить на навыки написания компиляторов?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Ты думаешь он будет его писать? Упаси Бог.

По сабжу, неужели поиск в гугле не даёт никакой информации?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

начать надо например с написания лексера и парсера токенов

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Если интерпретатор, разово, быстро, без оптимизаций и с боль-мень простым синтаксисом — ПРОСТО НАПИШИ! (на коленке). С Перлом ты знаком, вроде, вполне подойдет для написания интерпретатора.

Ты ж физик, соображалки хватит, там все не сложнее системы линейных ур-й. Ты ж не будешь читать книжку по линейке, если тебе надо простую систему линейных ур-й решить? И что такое детерминант знать не обязательно — просто решаешь, и все. Ну, если совсем ничего не знаешь, погугли про обратную польскую запись, тетрады и триады (Reverse Polish notation, quadruples, triples по-английски) — про синтаксические деревья общего вида (Abstract Syntax Tree) уже лишнее.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Dragon Book. на торент.сру была.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Он как раз и написал *компилятор*, вообще-то

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

> . разово, быстро, без оптимизаций.

то «тетрады и триады» необязательно. Можно генерить код на C/C++.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

> Он как раз и написал *компилятор*, вообще-то

Разница давно размыта.

Но тоже просто — транслируешь («интерпретеруешь»)в тетрады и заюзываешь одну из многочисленных библиотек для JIT. Или лопатишь в Це (Перл, Питон, Шелл — подставить по вкусу) и вызываешь его компилятор. Только не совсем понимаю надобности такого — все ж, наверное, топикстартер хотел именно интерпретатор.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

> . то «тетрады и триады» необязательно. Можно генерить код на C/C++.

Все равно де-факто изобретешь некую разновидность синтаксического дерева.

Простейший вариант — стековая машина и Польская строка (есть исчерпываюший пример — в русскоязычной даже — Википедии, http://ru.wikipedia.org/wiki/Обратная_польская_запись ), тетрады чуть менее тупы и до них додуматься проще ИМХО.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Любой учебник по языкам програмирования и методам трансляции (например Опалева, Самойленко) или т.н. драгон бук.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Каким местом она размыта? Вы вообще, батенька, в курсе что такое компилятор?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Физики неплохие компиляторы пишут. Некоторые из ранних реализаций Фортрана физиками сделаны. Mathematica написана физиком. Так что всё нормалёк.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

> Если интерпретатор, разово, быстро, без оптимизаций и с боль-мень простым синтаксисом — ПРОСТО НАПИШИ! (на коленке).

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

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

> Каким местом она размыта?

А всеми местами разом.

> Вы вообще, батенька, в курсе что такое компилятор?

А вы? Подозреваю, что не очень.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Меня очень долго мучает вопрос: Вот допустим тут вильфред собрался язык свой придумать (назовем его A )и компилятор для него, но ведь компилятор то будет работать не в интерпретаторе языка A, выходит что для исполнения произвольного кода на произвольном новом языке нужен другой язык B ранее существовавщий.

Как же тогда появился первый ЯП, ведь не всегда же были процессоры для выполнения кода.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Ну и почитай Бэкуса, как они самый первый компилятор Фортрана писали.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

Книга Дракона, второе издание.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

самый первый ЯП назывался «машинный код»

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

на LtU сегодня ссылка как раз забавная проскочила http://www.cc.gatech.edu/

Ziggurat is a framework for writing extensible programming languages, and for defining static semantics for those languages. In other words, it is a language designer’s toolkit.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

>Ziggurat is a framework for writing extensible programming languages, and for defining static semantics for those languages. In other words, it is a language designer’s toolkit.

ахха, я уже впечатлился. интересная штука

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

>> Если интерпретатор, разово, быстро, без оптимизаций и с боль-мень простым синтаксисом — ПРОСТО НАПИШИ! (на коленке).

>Очень паршивый подход. Так можно родить только кривое и убогое тормозилово.

Очень часто этого достаточно. «Вам шашечки, или ехать?» Многие физики так поступают, не зная даже слова «интерпретатор». Для физиков с математикам (в отличие от ИТшников) разработка простейшей «ad hoc» теории — состояние вполне привычное.

> Это всё ж таки наука, в которой есть некоторое количество теории.

См. пример выше. Линейка — вполне себе наука, однако школьники решают линейные системы, ничего об этой науке не зная. Нам в каком-то типа 5 классе на дом математичка задавала (факультатив то был, есснно) — придумать, как решить систему линейных ур-ий. Почти все «неравнодушные» к математике сами без труда разобрались.

Re: [чайник] где прочитать, как самостоятельно написать свой компилятор своего языка?

> Очень часто этого достаточно. «Вам шашечки, или ехать?» Многие физики так поступают, не зная даже слова «интерпретатор».

Так в том и дело, что по науке — проще и быстрее сделать, чем от балды. Намного проще.

А наука та — тупая и маленькая. Так что, вполне есть смысл ее поучить.

На чём пишут компиляторы?

18.04.2011, 10:25

Посмотрите, о чём в дампе пишут.
Добрый день Посмотрите, о чём в дампе пишут. Работает-работает винда, месяц, два. А потом синий.

компиляторы ?
Вот хотел бы узнать , существуют ли вообще компиляторы которые к примеру часть кода написанного в.

Компиляторы
Начал изучение ассемблера. Установил TASM и MASM. Почему на втором компиляторе при стандартной.

Компиляторы
Стало интересно, а сложны ли компиляторы функциональных языков, по сравнению с императивными, и.

Компиляторы
Скажите пожалуйста,я пользуюсь VS 2010,и при создании проекта сразу нажимаю финиш,затем у меня.

18.04.2011, 11:46 2 18.04.2011, 11:51 [ТС] 3 18.04.2011, 11:53 4
18.04.2011, 11:53
18.04.2011, 11:58 [ТС] 5
18.04.2011, 12:01 6

. объясняю на пальцах для одаренных :

gcc _КОМПИЛЯТОР_ с _ОТКРЫТЫМ_ исходным текстом . значит тебе только остается зайти в репозиторий сорцов либо скачать их и глянуть на чем написано , тоже самое и с clang , также зайти и глянуть на чем он написан

18.04.2011, 12:07 [ТС] 7

Только вместо ожидаемого кода самого компила по ссылке предлагаются примеры фрагментов компилируемых программ.

Добавлено через 1 минуту
Причём, gcc у меня установлен, но как заглянуть в его исходник, я всё равно не понимаю.

18.04.2011, 12:09 8

Только вместо ожидаемого кода самого компила по ссылке предлагаются примеры фрагментов компилируемых программ.

Причём, gcc у меня установлен, но как заглянуть в его исходник, я всё равно не понимаю.

а теперь проследуй в биореактор.

18.04.2011, 12:11 [ТС] 9

Здесь исходника самого компила тоже не видно.

Добавлено через 1 минуту

а теперь проследуй в биореактор.

GCC: Anonymous read-only SVN access

Our SVN source repository is available read-only to the public at large. That way you can pick up any version (including releases) of GCC that is in our repository.

Our web pages are still maintained via CVS, and can be accessed using the directions for our CVS setup.

In addition you can browse our SVN history online.
Using the SVN repository

Assuming you have version 1.0.0 and higher of Subversion installed, you can check out the GCC sources using the following command:

svn checkout svn://gcc.gnu.org/svn/gcc/trunk SomeLocalDir

If you are behind a firewall that does not allow the svn protocol through, you can replace svn:// with http://. You may also need to modify your subversion servers file (

/.subversion/servers) to set http-proxy-host and http-proxy-port. You should only use the http protocol if the svn protocol does not work; the http protocol has a higher server overhead associated with it and will be slower.

There is more information about Subversion specifically for GCC in the GCC Wiki.
Generated files

Our source tree contains a number of files that are generated from other source files by build tools such as Bison, Autoconf, and Gperf. Bison is now required when using SVN to access our sources, but all other generated files are included in the source tree so that GCC can be built without these build tools. The SVN checkout and update operations do not insure that the timestamps of generated files are later than those of the files they are generated from. The script contrib/gcc_update updates the timestamps for all these generated files. See the comments in that script for instructions on running it.

GCC’s build system (in particular Make) uses file timestamps to determine if a generated file needs to be updated by running a particular build tool. Because of this, GCC’s build system may believe that a generated file needs regenerating even though its source has not changed, and require a particular build tool to rebuild that generated file. If the appropriate build tool is installed on your system, then this will not be a problem. If you do not intend to make changes to the source, you can avoid installing these build tools by running contrib/gcc_update.

There has been some discussion of removing these generated files from GCC’s SVN source tree (there is no discussion of removing them from the released source tarballs). If that happens then building GCC from the SVN source tree would require installing the above mentioned build tools. Installing these build tools is not particularly difficult, but can be time consuming especially if you only occasionally install GCC on a particular system.

The build tools that GCC uses are all available from the GNU Project (see http://www.gnu.org), are often already available on many systems, and can often be found already built for some systems. A partial list of these build tools is: Autoconf, Bison, Xgettext, Automake, and Gperf.
Conflicts when using svn update

It is not uncommon to get svn conflict messages for some generated files when updating your local sources from the SVN repository. Typically such conflicts occur with autoconf generated files.

As long as you haven’t been making modifications to the generated files or the generator files, it is safe to delete the offending file, then run svn update again to get a new copy.
Branches and Tags

A branch called branchname can be checked out with the following command:

svn co svn://gcc.gnu.org/svn/gcc/branches/branchname gcc

(The release branch of the latest version of GCC x.y is named gcc-x_y-branch.)

Similarly a tag called tagname can be checked out with the following command:

svn co svn://gcc.gnu.org/svn/gcc/tags/tagname gcc

(For recent releases, the SVN tag for GCC X.Y.Z is of the form gcc_X_Y_Z_release.)

The following list provides some representative examples:

* gcc-4_3-branch
* gcc_4_3_4_release
* gcc_4_3_3_release
* gcc_4_3_2_release
* gcc_4_3_1_release
* gcc_4_3_0_release
* gcc-3_4-branch
* gcc_3_4_3_release
* gcc_3_4_2_release
* gcc_3_4_1_release
* gcc_3_4_0_release

To get a list of available branches, use the command:

svn ls svn://gcc.gnu.org/svn/gcc/branches

To find out the revision/date at which a branch or tag was created, use the command svn log —stop-on-copy.
Active Development Branches
General Infrastructure

struct-reorg-branch
This branch is for the development of structure reorganization optimizations, including field reordering, structure splitting for trees. These optimizations are profile information driven. This is a subbranch of tree-profiling. This branch is being maintained by Caroline Tice, Dale Johannesen, Kenneth Zadeck, Stuart Hastings, Mostafa Hagog.
autovect-branch
This branch is the successor to the lno-branch. The purpose of this branch is tree-level autovectorization work, and related work that the autovectorizer could use or benefit from (like data-dependence analysis, loop nest optimizations).
graphite-branch
The purpose of this branch is to develop an infrastructure for loop transforms using the polyhedral model.
lw-ipo
This branch aims to implement lightweight IPO. Patches and discussion on this branch should be marked with the tag [lipo] in the subject line. The branch is maintained by David Li.
gimple-front-end
This branch implements a front end for GIMPLE. It is maintained by Diego Novillo. Patches should be prefixed with [gimplefe] in the subject line. See the GIMPLE Front End page for details.
ra-improvements
This branch aims to implement several improvements to the current register allocator. Examples include implementing a lower-triangular conflict matrix and register coalescing. It is hoped that these improvements will not only help the current allocator, but will be useful to the other register allocation projects such as RABLE and YARA. This branch will be merged with the dataflow-branch from time to time. The patches for this branch should be marked with the tag [ra-improvements] in the subject line. The branch is maintained by Peter Bergner.
ira
This branch contains the Integrated Register Allocator (IRA). It is based on work done on yara-branch. The latter is more of a research branch because one of its goals (removing reload) is too remote. The ira branch is focused to prepare some code for GCC mainline, hopefully in time for GCC 4.4. IRA still uses reload; it is called integrated because register coalescing and register live range splitting are done on-the-fly during coloring. The branch is maintained by Vladimir Makarov and will be merged with mainline from time to time. Patches will be marked with the tag [ira] in the subject line.
ira-merge
This branch contains bug fixes for the Integrated Register Allocator (IRA). It is branched from trunk at revision 139590 when IRA was merged into trunk. It is used to track IRA related regressions. Only IRA fixes from trunk will be applied to this branch. Its goal is there should be no «make check» and performance regressions against trunk at revision 139589. The branch is maintained by H.J. Lu and Vladimir Makarov .
sel-sched-branch
This branch contains the implementation of the selective scheduling approach. The goal of the branch is to provide more aggressive scheduler implementation with support for instruction cloning, register renaming, and forward substitution. The branch is maintained by Andrey Belevantsev and Maxim Kuvyrkov and will be regularly merged with mainline. Patches will be marked with the tag [sel-sched] in the subject line.
incremental-compiler
This branch contains change to turn GCC into an incremental compiler. The branch is maintained by Tom Tromey tromey@redhat.com. Patches for this branch should be marked with the tag [incremental] in the subject line.
gc-improv
This branch is for the development of garbage collector improvements. It is the successor to the boehm-gc branch, but without integration with Boehm’s GC. The branch is maintained by Laurynas Biveinis. Patches for this branch should be marked with the tag [gc-improv] in the subject line.
milepost-branch
This branch is for GCC developments done in the Milepost project. (http://www.milepost.eu). The branch is maintained by Mircea Namolaru namolaru@il.ibm.com. Patches should be marked with the tag [mpost] in the subject line.
melt-branch
This branch is for a Middle End Lisp Translator branch, including both the plugin Lisp-like facility and static analyzers developed with it. This branch is maintained by Basile Starynkevitch basile@starynkevitch.net. Use the [MELT] tag for patches.
stack
This branch contains a new stack alignment framework to automatically align stack for local variables with alignment requirement. The branch is maintained by H.J. Lu , Joey Ye and Xuepeng Guo . Patches should be marked with the tag [stack] in the subject line.
thread-annotations
This branch contains the implementation of thread safety annotations and analysis (http://gcc.gnu.org/wiki/ThreadSafetyAnnotation). The branch is maintained by Le-Chun Wu. Patches and discussion on this branch should be marked with the tag [thread-annotations] in the subject line.
rtl-fud-branch
This branch is for the development of factored use-def chains as an SSA form for RTL. Patches should be marked with the tag [rtl-fud] in the subject line. The branch is maintained by Steven Bosscher and Kenneth Zadeck.
transactional-memory
This branch is for the development of transactional memory support for GCC. Patches for this branch should be marked [trans-mem] in the subject line. The branch is maintained by Richard Henderson.
cxx-mem-model
This branch is for the implementation of the C++ memory model. Patches for this branch should be marked [cxx-mem-model] in the subject line. The branch is maintained by Aldy Hernandez.
dwarf4
This branch is for support of DWARF-4 features. DWARF-4 is currently under development, so changes on this branch will remain experimental until Version 4 is officially finalized.
plugins
This branch adds plugin functionality to GCC. See the plugins wiki page for details.
no-undefined-overflow
This branch is for tracking overflow behavior on expressions rather than on types. Patches should be marked with the tag [no-undefined-overflow] in the subject line. The branch is maintained by Richard Guenther.
debuglocus
This branch is an experiment to see whether improved debug information can be maintained throughout the compiler by associating a user decl with an expression, statement, or insn. The name comes from attempting to utilize the ever present source location (locus) field to carry the debug info. Further information can be found on the debuglocus wiki page .
alias-export
This branch contains the alias export and data dependency export patch. It is used to experiment with the propagation process. This branch is maintained by Andrey Belevantsev abel@ispras.ru.
vect256
This branch is for extending vectorizer to 256bit. The branch is maintained by Richard Guenther and H.J. Lu. Patches should be marked with the tag [vect256] in the subject line.

cygwin-improvements
This branch is intended as a development and proving grounds for fixes and enhancements specifically to the Cygwin port of the compiler, although some of these may touch slightly on MinGW targets as well. It is maintained by Dave Korn and open to contributions from any interested party; please tag patches with «[cygwin-improvements]» in the title line and post them to the GCC Patches list with a Cc: to that address.

fortran-dev
This branch is for disruptive changes to the Fortran front end, especially for OOP development and the array descriptor update. It is maintained by Jerry DeLisle .
fortran-exp
This branch is for experimental changes to the Fortran front end, initially for array constructor refactoring using splay-tree and other areas of optimization. It is maintained by Jerry DeLisle .
gccgo
This branch is for the Go frontend to gcc. For more information about the Go programming language, see http://golang.org. The branch is maintained by Ian Lance Taylor. Patches should be marked with the tag [gccgo] in the Subject line.
gupc
This branch implements support for UPC (Unified Parallel C). UPC extends the C programming language to provide support for high-performance, parallel systems with access to a single potentially large, global shared address space. Further information can be found on the GNU UPC web page.
gcc-4_4-plugins
This branch is for backporting the plugin functionality into a 4.4-based release. There will be no new code or functionality added to this branch. It is maintained by Diego Novillo. Only patches backported from mainline are accepted. They should be marked with the tag [4_4-plugins] in the Subject line.
pph
This branch implements Pre-Parsed Headers for C++. It is maintained by Diego Novillo and Lawrence Crowl. Patches should be prefixed with [pph] in the subject line.

These branches are maintained by organizations distributing GCC. No changes should be made to those branches without the explicit permission of the distributing organization. The branch name should be prefixed with the initials of the distributing organization.

apple-local-200502-branch
This branch is for various improvements in use at Apple and to coordinate work with others. This branch is maintained by the folks at Apple. Previous branch was apple-ppc-branch.
csl-3_3_1-branch
CodeSourcery release based on GCC 3.3.1.
csl-arm-2004-q3-branch
CodeSourcery ARM 2004-Q3 release
csl-3_4-linux-branch
CodeSourcery GNU/Linux compilers based on GCC 3.4.x.
csl-3_4_3-linux-branch
CodeSourcery GNU/Linux compilers based on GCC 3.4.3, with patches from the csl-arm-branch.
csl-gxxpro-3_4-branch
CodeSourcery’s Sourcery G++ compilers, based on GCC 3.4.x.
csl-sol210-3_4-branch
CodeSourcery branch for developing Solaris 2.10 AMD64 support for GCC 3.4; this branch is used for the system compilers in OpenSolaris. This branch is maintained by CodeSourcery personnel. Patches should be marked with the tag [csl-sol210-branch] in the subject line.
google/integration
This branch contains some minimal patches that are likely not useful anywhere outside of Google’s build environment. These are typically configuration patches. The branch is maintained by Diego Novillo dnovillo@google.com.
google/main
This branch contains Google local patches that are staged to be contributed to trunk. Some of these patches are either in the process of being reviewed, or have not yet been proposed. The intent of this branch is to serve as a staging platform to allow collaboration with external developers. Patches in this branch are only expected to remain here until they are reviewed and accepted in trunk. This branch is maintained by Diego Novillo dnovillo@google.com.
ibm/gcc-4_1-branch
This branch provides decimal float support backported to GCC 4.1.x. It is expected to be used primarily within IBM for PowerPC-64 GNU/Linux. The branch is maintained by Janis Johnson .
ibm/gcc-4_3-branch
This branch is expected to be used primarily within IBM for PowerPC-64 GNU/Linux.
ibm/gcc-4_4-branch
This branch is expected to be used primarily within IBM for PowerPC-64 GNU/Linux.
ibm/power7-meissner
This branch is a private development branch for Power7 (PowerPC ISA 2.06) development, prior to the patches being submitted to the mainline. The branch is maintained by Michael Meissner, meissner@linux.vnet.ibm.com.
redhat/gcc-3_2-branch
Red Hat GNU/Linux compilers based on GCC 3.2.x.
redhat/gcc-3_4-branch
Red Hat GNU/Linux compilers based on GCC 3.4.x.
redhat/gcc-4_0-branch
Red Hat GNU/Linux compilers based on GCC 4.0.x.
redhat/gcc-4_1-branch
Red Hat GNU/Linux compilers based on GCC 4.1.x.
redhat/gcc-4_3-branch
Red Hat GNU/Linux compilers based on GCC 4.3.x.
suse/gcc-4_1-branch
SUSE GNU/Linux compilers based on GCC 4.1.x.
suse/gcc-4_2-branch
SUSE GNU/Linux compilers based on GCC 4.2.x.
ubuntu/gcc-4_2-branch
This branch follows the gcc-4_2-branch, except for gcc/java, boehm-gc, libffi, libjava and zlib, which are backported from the trunk (and from gcc-4_3-branch, once created). The branch is used as the base for the Debian and Ubuntu gcc-4.2 source package.

Inactive Development Branches

dfp-branch
edge-vector-branch
cp-parser-branch
cp-parser-branch-2
pch-branch
gcc-3_4-basic-improvements-branch
mips-3_4-rewrite-branch
dfa-branch
gcj-abi-2-dev-branch
gcj-eclipse-branch
tree-ssa-20020619-branch
csl-sol210-branch (Solaris 2.10 AMD64 support)
gomp-20050608-branch
gomp-3_0-branch
fixed-point
gimple-tuples-branch
c-4_5-branch
alias-improvements
cond-optab
var-tracking-assignments*-branch
mem-ref2
These branches have been merged into the mainline.
apple-ppc-branch
This branch was for various improvements in use at Apple and to coordinate work with others. This branch was maintained by the folks at Apple. It has been superseded by apple-local-200502-branch.
stree-branch
This branch was for improving compilation speed and reducing memory use by representing declarations as small flat data structures whenever possible, lazily expanding them into full trees when necessary. This branch was being maintained by Matt Austern, Robert Bowdidge, Geoff Keating, and Mike Stump. Patches were marked with the tag [stree] in the subject line.
compile-server-branch
This branch was aimed at improving compile speed by caching work done between compilations. The work saved is mainly related to header file processing. This branch was maintained by Mike Stump and Per Bothner. Patches were marked with the tag [cs] in the subject line.
libobjc-branch
The branch is aimed to clean up libobjc and make it run on Darwin. Patches should be marked with the tag [libobjc-branch] in the subject line. Patches can be approved by Andrew Pinski

or Nicola Pero .
cfg-branch
This branch was created to develop and test infrastructure for easier writing of new RTL based optimizations. The branch was based on GCC pre-3.3 and has been partially merged into the mainline for GCC 3.4. It is now closed, and work continues on the rtlopt-branch.
pointer_plus
This branch is for the development of POINTER_PLUS_EXPR. Which is to be used instead of casting between an integer type and a pointer type before doing pointer addition. This branch is being maintained by Andrew Pinski. Patches for this branch should be marked with the tag [PTR-PLUS] in the subject line, and CC’ed to Andrew Pinski.
tree-ssa-cfg-branch
This branch has been merged into the tree-ssa-20020619-branch.
ast-optimizer-branch
The purpose of this branch was to improve GCC’s tree based optimizations. The patches of this branch have been moved to the tree-ssa-20020619-branch.
faster-compiler-branch
This was a temporary branch for compiler speedups for GCC 3.4. See this thread for discussion of possible work still to be done in this area. The branch is unmaintained at present.
gcc-3_3-e500-branch
This branch was for backporting the PowerPC/E500 back end to GCC 3.3. See this message for details.
gcc-3_4-e500-branch
This branch was for stabilization of the powerpc-*spe architecture, and for adding support for the 8548 chip (e500 v2). This branch was maintained by Aldy Hernandez. All the e500 support was merged to mainline.
gomp-01-branch
gomp-branch
These two branches were initial attempts to implement OpenMP support in GCC. They were never properly maintained and have now been superseded by gomp-20050608-branch.
lno-branch
A sub-branch of tree-ssa that aims at implementing a loop nest optimizer at the tree level. Was largely merged into mainline, and is currently unmaintained. This work now continues on the autovect-branch.
java-gui-branch
This was a temporary branch for development of java GUI libraries (AWT and Swing) in the libjava directory. It has been superseded by java-gui-20050128-branch
java-gui-20050128-branch
This was a temporary branch for development of java GUI libraries (AWT and Swing) in the libjava directory. It has been merged into mainline.
gcjx-branch
This branch was used for development of gcjx, a rewrite of the front end for the Java programming language. It has been superseded by gcj-eclipse-branch.
csl-hpux-branch
This branch was for changes to G++ to be more compatible with ABI bugs in the HP-UX C++ compiler. It is now unmaintained.
tree-cleanup-branch
This branch contained improvements and reorganization to the tree optimizers that were not ready in time for GCC 4.0. The goal was to cleanup the tree optimizers and improve the sequencing of the passes. It has now been merged into mainline for the 4.1 release.
bje-unsw-branch
This branch was dedicated to some research work by Ben Elliston at the University of New South Wales (UNSW) on transformation phase ordering. It will never merge with mainline, although a selection of patches may be submitted over time. Deleted by revision 152653.
redhat/gcc-3_3-branch
This branch used to hold Red Hat GNU/Linux compilers based on GCC 3.3.x.
rtlopt-branch
This branch was the successor to the cfg-branch, with the exception that it was based on GCC pre-3.4. The purpose of the branch was to develop and test infrastructure for CFG based code improving transformations on RTL.
killloop-branch
The missing optimizations and optimization improvements necessary for removing the old loop optimizer were developed on this branch. Most of these changes were merged in 4.2.
ssaupdate-branch
This branch served to clean up and improve utilities for the SSA form updating, as well as for related changes of the SSA form representation. Most of the changes in this branch were never merged. Part of them were incorporated in Diego Novillo’s SSA updating improvement patch.
predcom
This branch aimed to implement predictive commoning optimization and to introduce the changes to the representation of Fortran arrays, alias analysis and dependency analysis to make it useful for the common applications (e.g., mgrid). The branch was merged in 4.3.
dataflow-branch
This branch has been merged into mainline on June 6, 2007 as svn revision 125624. It used to contain replacement of backend dataflow with df.c based dataflow. The branch was maintained by Daniel Berlin and Kenneth Zadeck
cxx0x-branch
This branch was for the development of C++0x features, and all features developed on this branch have been merged to mainline. Future C++0x features will be developed against mainline. This branch was deleted at revision 152320.
cxx0x-concepts-branch
This branch contains the beginnings of a re-implementation of Concepts, a likely future feature of C++, using some of the code from the prototype implementation on conceptgcc-branch. It is not currently maintained.
cxx0x-lambdas-branch
This branch was for the development of lambda functions, a coming feature in C++0x. It was merged into the trunk at revision 152318.
tree-profiling-branch
This branch was for the development of profiling heuristics and profile based optimizations for trees, such as profile driven inline heuristics. Another goal of this branch was to demonstrate that maintaining the CFG and profile information over expanding from GIMPLE trees to RTL is feasible and can bring considerable performance improvements. It is no longer maintained.
new-regalloc-branch
Daniel Berlin and Michael Matz were working on an implementation of a graph-coloring register allocator on this branch. It is known to bootstrap under x86-linux-gnu and ppc-linux-gnu. It is no longer maintained.
structure-aliasing-branch
This branch contains improvements to the tree optimizers ability to do pointer-to-structure aliasing analysis and optimization. This involves some significant rework of the way our memory information is represented in the tree-ssa form. The branch was maintained by Daniel Berlin. It is no longer maintained.
cfo-branch
The goal of this branch was to add a new extension for improving the code size optimization of GCC with code factoring methods (code motion and merging algorithms). It is no longer maintained.
reload-branch
This branch contains a version of reload in which the tracking of reload register lifetimes and the inheritance code has been rewritten in an attempt to make it more maintainable. It is no longer maintained.
dead/improved-aliasing-branch
This branch contains improvements to the tree-based aliasing infrastructure. The branch was maintained by Daniel Berlin and Diego Novillo . It is no longer maintained.
sched-treegion-branch
This branch was for the development of a treegion-based instruction scheduler. The branch was maintained by Chad Rosier. It is no longer maintained.
mem-ssa
This branch contains the implementation of Memory SSA, a new mechanism for representing memory operations in SSA form (http://gcc.gnu.org/ml/gcc/2006-02/msg00620.html). The branch was maintained by Diego Novillo. It is no longer maintained.
yara-branch
This branch contains Yet Another Register Allocator (YARA). The branch was maintained by Vladimir Makarov . It is no longer maintained; some of the work was used as a basis for the work on the ira branch.
opt-diary
This branch contains the implementation of Optimization Diary, a collection of useful log information generated by the optimizers. This branch was maintained by Devang Patel. It is no longer maintained.
insn-select
This branch aimed to implement in early instruction selection and register class selection pass, which runs before register allocation and subsumes the current regclass pass. In particular the goal is to chose an alternative per instruction, usable as a base during register allocation, which ideally is not changed during reload if registers could be allocated. This will not be possible in all cases, especially when addresses generated during spilling will be invalid on the target machine. But we should be able to do away with fake register classes representing strict unions of other register classes. The branch was maintained by Michael Matz. It is no longer maintained.
addressing-modes
This branch aimed to clean up the way base and index registers are handled by target headers. In particular, the strict and non-strict meaning of these registers are unified and a common API is presented to implementations of the target macros. Obsolete target macros will also be removed. The branch was maintained by Paolo Bonzini. It is no longer maintained.
csl-arm-branch
CodeSourcery branch for developing ARM back end improvements. The branch was maintained by CodeSourcery personnel. It is no longer maintained; almost all the patches have been merged to mainline.
csl/coldfire-4_1
CodeSourcery branch for developing ColdFire back end improvements. The branch was maintained by CodeSourcery personnel. It is no longer maintained; almost all the patches have been merged to mainline.
ia64-fp-model-branch
This branch was a development branch with the goal of implementing the improvements and features discussed at the ia64 floating point page on the GCC wiki. It was maintained by Zack Weinberg . It is no longer maintained.
ia64-improvements
The goal of this branch was to improve the performance of binaries generated with GCC on the Itanium processor. Details of current projects on this branch can be found at the Gelato GCC wiki and at the IA-64 improvements page. This branch was maintained by Robert Kidd and Diego Novillo. It is no longer maintained.
cxx-reflection-branch
Part of the work on providing support for compile time reflection in C++ was done in this branch. This branch was maintained by Gabriel Dos Reis . It is no longer maintained.
hammer-3_3-branch
The goal of this branch was to have a stable compiler based on GCC 3.3 with improved performance for AMD’s 64-bit Hammer CPUs. The branch was maintained by Jan Hubicka and Andreas Jaeger . Patches added on this branch might not be appropriate for the GCC 3.3 branch due to our policies concerning release branches. All patches were added to mainline GCC (for 3.4).
objc-improvements-branch
This branch was originally used to merge Objective-C bug fixes and enhancements from Apple Computer into the FSF tree; this has now been completed. A later purpose of the branch was to implement the Objective-C++ language in the FSF GCC source tree. The message thread starting here describes this at more length. This branch was being maintained by Zem Laski . It is no longer maintained.
libada-gnattools-branch
This is the spiritual successor to the libada branch. This branch exists to solve bug 5911 and others, by breaking out the Ada runtime into a libada directory and the Ada tools into a gnattools directory. Work was devoted to cleaning up the configure and make machinery, and separating it as much as possible from the GCC build machinery. Nathanael Nerode maintained this branch. It is no longer maintained.
libstdcxx_so_7-branch
This was a branch for experimental work on the C++ Runtime Library (libstdc++-v3) beyond the current version 6 library ABI. Paolo Carlini

and Benjamin Kosnik were maintaining this branch. It is no longer maintained.
function-specific-branch
This branch is for development of adding function specific options to GCC. See the GCC wiki for a more detailed project description. Patches should be marked with the tag [function-specific] in the subject line. The branch has been merged into GCC 4.4.
lto-streamer
This was a sub-branch of the lto branch. It was intended for unstable work related to the conversion from DWARF encoding to GIMPLE streamer. It is no longer maintained.
plugin
This branch contains work for a plugin infrastructure in GCC to enable additional checking work. This branch is maintained by Eric Christopher echristo@gmail.com and will be merged with mainline from time to time. Patches will be marked with the tag [plugin] in the subject line.
condate-branch
The purpose of this branch is to develop a language for checking control flow graph properties. The code of this branch has not been merged in trunk.
miro-branch
The purpose of this branch is to develop an improved Mudflap with referent objects. The code of this branch has not been merged in trunk.
var-mappings-branch
This branch is for improving debug information based on tracking multiple variables per computed value. The branch is maintained by Richard Guenther and Michael Matz. Patches should be marked with the tag [varmap] in the subject line.
mem-ref
This branch is for lowering the GIMPLE IL for memory accesses to a flat representation. See the GCC wiki for a more detailed project description. The branch is maintained by Richard Guenther. Patches should be marked with the tag [mem-ref] in the subject line.
gcc-in-cxx
This branch was for converting GCC to be written in C++. The branch was maintained by Ian Lance Taylor.
ibm/power7-tmp
This branch was used to stage patches for Power7 (PowerPC ISA 2.06) from the development branch to the mainline. The branch was maintained by Michael Meissner, meissner@linux.vnet.ibm.com.
lto
This branch implemented link-time optimization.
named-addr-spaces-branch
This branch was the development branch to add named address space support for architectures that have multiple address spaces. The CELL/spu architecture adds an __ea keyword to describe extended memory in the host chip address space instead of the local CELL/spu address space. The branch was created by Ben Elliston, modified by Michael Meissner and eventually maintained by Ulrich Weigand. All changes from this branch were merged into mainline.
named-addr-4_3-branch
The goal of this branch was to backport the changes from the named-addr-spaces-branch to a GCC 4.3 tree. This branch was maintained by Michael Meissner. This branch was merged from gcc-4_3-branch.
split
For development of stack splitting, as described on the GCC wiki. This branch was maintained by Ian Lance Taylor. All changes were merged into mainline.
boehms-gc
The goal of this branch was to test Boehm’s GC feasibility as the garbage collector for GCC proper. This was a part of Google Summer of Code project, described in detail at http://gcc.gnu.org/wiki/Garbage_collection_tuning. The branch was maintained by Laurynas Biveinis.

For questions related to the use of GCC, please consult these web pages and the GCC manuals. If that fails, the gcc-help@gcc.gnu.org mailing list might help. Comments on these web pages and the development of GCC are welcome on our developer list at gcc@gcc.gnu.org. All of our lists have public archives.

Copyright (C) Free Software Foundation, Inc. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.

These pages are maintained by the GCC team. Last modified 2011-04-15.

Можно ли написать компилятор в машиный код на языке очень высокого уровня?

Можно ли написать компилятор в машиный код на языке очень высокого уровня?

1. Поверьте человеку, который пишет на Си с 1985 года (30 лет, вроде бы?) — НИКОГДА не пишите на Си ничего, если только к вашему виску не приставили пистолет. Исключение одно — ядро ОС. Да и то.

2. Что угодно можно написать на чём угодно. Вопрос удобства.

3. Писать компилятор надо на языке с развитыми средствами поддержки жизни проекта. Таких два — Java и C#. Можно (а если Вам это комфортно, то и нужно) использовать функциональные расширения соответствующих платформ. Scala/F#.

4. На говноязыках серьёзные вещи писать не нужно. Ключевое свойство говноязыка — обсуждение вокруг него о том, как бедные программеры перетрудились явно прописывать руками типы всех переменных. На таких ЯП можно писать затычки и примочки.

5. Не применяйте генераторы лексических и грамматических анализаторов, пока не научитесь писать компилятор руками. Ключевое слово — парсинг рекурсивным спуском. Это реально просто, если грамматика языка — LR1. Для начала надо взять простой язык. Очень простой.

6. Базовый компилятор с кодогенерацией для стековой машины нужно уметь писать за два дня. Если вы хотите это уметь.

7. Бекэнды (реальную кодогенерацию) писать НЕ НУЖНО. Вообще. Вы её хорошо не напишете ни-ко-гда. Проще генерировать на выходе Си и докомпилировать приличным си-компилятором.

Как написать очень простой компилятор

Дополнительные компиляторы, такие как gcc , компилируют коды в машиносчитываемые файлы в соответствии с языком, на котором был написан код (например, C, C ++ и т. д.). Фактически, они интерпретируют смысл каждого кода в соответствии с библиотекой и функциями соответствующих языков. Исправьте меня, если я ошибаюсь.

Я хочу лучше понять компиляторы, написав очень простой компилятор (возможно, в C) для компиляции статического файла (например, Hello World в текстовом файле). Я пробовал некоторые учебники и книги, но все они предназначены для практических случаев. Они имеют дело с компиляцией динамических кодов со значениями, связанными с соответствующим языком.

Как я могу написать базовый компилятор для преобразования статического текста в машиночитаемый файл?

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

Внедрение практических руководств и ресурсов высоко оценено: -)

5 ответов

Введение

Типичный компилятор выполняет следующие шаги:

  • Анализ: исходный текст преобразуется в абстрактное синтаксическое дерево (AST).
  • Разрешение ссылок на другие модули (C откладывает этот шаг до привязки).
  • Семантическая проверка: отсеивание синтаксически правильных утверждений, которые не имеют смысла, например. недостижимый код или дубликаты деклараций.
  • Эквивалентные преобразования и оптимизация высокого уровня: AST преобразуется для представления более эффективного вычисления с той же семантикой. Это включает, например, ранний расчет общих подвыражений и постоянных выражений, устраняя чрезмерные локальные назначения (см. также SSA ) и т. д.
  • Генерация кода: AST преобразуется в линейный низкоуровневый код со скачками, распределением регистров и т. п. Некоторые вызовы функций могут быть встроены на данном этапе, некоторые петли развернуты и т. Д.
  • Оптимизация в режиме ожидания: низкоуровневый код сканируется для устранения простой локальной неэффективности.

Большинство современных компиляторов (например, gcc и clang) повторяют последние два шага еще раз. Они используют промежуточный низкоуровневый, но независимый от платформы язык для начальной генерации кода. Затем этот язык преобразуется в код, специфичный для платформы (x86, ARM и т. Д.), Делая примерно то же самое в оптимизированной платформе. Это включает, например, использование векторных инструкций, когда это возможно, переупорядочение команд для повышения эффективности прогнозирования ветвей и т. д.

После этого объектный код готов к связыванию. Большинство компиляторов с собственным кодом знают, как вызвать компоновщик для создания исполняемого файла, но это не сам шаг компиляции. В таких языках, как соединение Java и C #, может быть полностью динамическим, выполняемым VM во время загрузки.

Вспомните основы

  • Заставьте это работать.
  • Сделайте это красивым.
  • Сделать это эффективным

Эта классическая последовательность применяется ко всей разработке программного обеспечения, но имеет повторение.

Сосредоточьтесь на первом шаге последовательности. Создайте простейшую вещь, которая могла бы работать.

Прочитайте книги!

Прочитайте книгу Драконов от Ахо и Ульмана. Это классика и до сих пор вполне применима сегодня.

Если этот материал слишком тяжел для вас прямо сейчас, сначала прочитайте несколько инструкций по разбору; обычно библиотеки разбора включают в себя и примеры.

Убедитесь, что вам удобно работать с графиками, особенно с деревьями. Эти вещи — это программы, созданные на логическом уровне.

Хорошо определить свой язык

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

Пришло время писать фрагменты кода на вашем новом языке в качестве тестовых примеров для будущего компилятора.

Используйте свой любимый язык

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

Также можно писать разные этапы компилятора на разных языках, если это необходимо.

Подготовьтесь написать много тестов

Весь ваш язык должен быть охвачен тестовыми примерами; эффективно они будут определены ими. Ознакомьтесь с вашими предпочтениями. Напишите тесты с первого дня. Сосредоточьтесь на «положительных» тестах, которые принимают правильный код, в отличие от обнаружения неправильного кода.

Регулярно выполняйте все тесты. Исправьте неисправные тесты перед продолжением. Было бы обидно, если бы в итоге появился плохой язык, который не может принять действительный код.

Создайте хороший парсер

Множителей Parser много . Выберите все, что захотите. Вы также можете написать свой собственный парсер с нуля, но это стоит того, если синтаксис вашего языка dead прост.

Анализатор должен обнаруживать и сообщать синтаксические ошибки. Напишите много тестовых примеров, как положительных, так и отрицательных; повторите использование кода, который вы написали, определяя язык.

Вывод вашего синтаксического анализа — абстрактное синтаксическое дерево.

Если на вашем языке есть модули, вывод анализатора может быть простейшим представлением созданного вами «объектного кода». Существует множество простых способов сбросить дерево в файл и быстро загрузить его.

Создать семантический валидатор

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

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

Снова напишите и запустите много тестовых примеров. Тривиальные случаи необходимы для устранения неполадок как умных и сложных.

Сгенерировать код

Используйте самые простые методы, которые вы знаете. Часто нормально преобразовать конструкцию языка (например, инструкцию if ) в шаблон с легким параметризацией, мало чем отличающийся от шаблона HTML.

Опять же, игнорируйте эффективность и сосредоточьтесь на правильности.

Задайте независимую от платформы низкоуровневую VM

Я предполагаю, что вы игнорируете материал низкого уровня, если вы не заинтересованы в деталях, связанных с оборудованием. Эти детали являются gory и сложными.

  • LLVM: позволяет эффективно генерировать машинный код, обычно для x86 и ARM.
  • CLR: цели .NET, в основном x86 /Windows; имеет хороший JIT.
  • JVM: цели Java-мир, довольно многоплатформенный, имеет хороший JIT.

Игнорировать оптимизацию

Оптимизация сложная. Почти всегда оптимизация преждевременна. Создайте неэффективный, но правильный код. Внесите весь язык, прежде чем пытаться оптимизировать полученный код.

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

Итак, что?

Если все это не слишком пугает вас, продолжайте! Для простого языка каждый из шагов может быть проще, чем вы думаете.

Увидев «Hello world» из программы, которую создал ваш компилятор, может стоить усилий.

Jack Crenshaw Давайте построим компилятор , в то время как незавершенный, представляет собой чрезвычайно читаемое введение и учебник.

Nicklaus Wirth Compiler Construction — очень хороший учебник по основам простой компоновки компилятора. Он сосредотачивается на реверсивном спуске сверху вниз, который, давайте посмотрим правде в глаза, намного проще, чем lex /yacc или flex /bison. Оригинальный компилятор PASCAL, написанный его группой, был сделан таким образом.

Другие люди упомянули разные книги Драконов.

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

Если вы действительно хотите написать только машиночитаемый код и не нацеливаться на виртуальную машину, вам нужно будет прочитать руководства Intel и понять

    а. Связывание и загрузка исполняемого кода

б . COFF и PE форматы (для окон), альтернативно понимают ELF формат (для Linux)

  • с. Понимать форматы файлов .COM (проще, чем PE) д. Понимать сборщики
  • е. Понимать компиляторы и механизм генерации кода в компиляторах.
  • Гораздо сложнее, чем сказано. Я предлагаю вам прочитать компиляторы и интерпретаторы в C ++ в качестве отправной точки (By Ronald Mak). Кроме того, «позволяет создавать компилятор» Crenshaw в порядке.

    Если вы не хотите этого делать, вы можете написать свою собственную виртуальную машину и написать генератор кода, ориентированный на эту виртуальную машину.

    Советы: Изучите Flex и Bison FIRST. Затем перейдите к созданию собственного компилятора /виртуальной машины.

    Подход DIY для простого компилятора может выглядеть так (по крайней мере, так выглядел мой проект uni):

    1. Определите грамматику языка. Контекст бесплатно.
    2. Если ваша грамматика еще не LL (1), сделайте это сейчас. Обратите внимание, что некоторые правила, которые выглядят нормально в простой грамматике CF, могут оказаться уродливыми. Возможно, ваш язык слишком сложный .
    3. Напишите Lexer, который разрезает поток текста в токены (слова, цифры, литералы).
    4. Напишите рекурсивный синтаксический анализатор нисходящей точки для вашей грамматики, который принимает или отклоняет ввод.
    5. Добавление синтаксического дерева в ваш синтаксический анализатор.
    6. Записать генератор машинного кода из дерева синтаксиса.
    7. Прибыль & amp; Пиво, в качестве альтернативы вы можете начать думать, как делать более интеллектуальный парсер или генерировать лучший код.

    Должно быть много литературы, описывающей каждый шаг в деталях.

    Как создать свой язык программирования: теория, инструменты и советы от практика

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

    Введение

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

    Тем не менее, я написал абсолютно новый язык. И он работает. Наверное, я что-то делаю правильно.

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

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

    Первые шаги

    «А с чего вообще начинать?» — вопрос, который другие разработчики часто задают, узнав, что я пишу свой язык. В этой части постараюсь подробно на него ответить.

    Компилируемый или интерпретируемый?

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

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

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

    Прим. перев. Кстати, у нас есть краткий обзор серии статей по созданию собственного интерпретатора — это отличное упражнение для тех, кто изучает Python.

    Выбор языка

    Своеобразный мета-шаг: язык программирования сам является программой, которую надо написать на каком-то языке. Я выбрал C++ из-за производительности, большого набора функциональных возможностей, и просто потому что он мне нравится.

    Но в целом совет можно дать такой:

    • интерпретируемый ЯП крайне рекомендуетсяписать на компилируемом ЯП (C, C++, Swift). Иначе потери производительности будут расти как снежный ком, пока мета-интерпретатор интерпретирует ваш интерпретатор;
    • компилируемый ЯП можно писать на интерпретируемом ЯП (Python, JS). Возрастёт время компиляции, но не время выполнения программы.

    Проектирование архитектуры

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

    Лексический анализатор / лексер

    Строка исходного кода проходит через лексер и превращается в список токенов.

    Первый шаг в большинстве ЯП — это лексический анализ. Говоря по-простому, он представляет собой разбиение текста на токены, то есть единицы языка: переменные, названия функций (идентификаторы), операторы, числа. Таким образом, подав лексеру на вход строку с исходным кодом, мы получим на выходе список всех токенов, которые в ней содержатся.

    Обращения к исходному коду уже не будет происходить на следующих этапах, поэтому лексер должен выдать всю необходимую для них информацию.

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

    Одним из основных таких инструментов является Flex — генератор лексических анализаторов. Он принимает на вход файл с описанием грамматики языка, а потом создаёт программу на C, которая в свою очередь анализирует строку и выдаёт нужный результат.

    Моё решение

    Я решил оставить написанный мной анализатор. Особых преимуществ у Flex я в итоге не увидел, а его использование только создало бы дополнительные зависимости, усложняющие процесс сборки. К тому же, мой выбор обеспечивает больше гибкости — например, можно добавить к языку оператор без необходимости редактировать несколько файлов.

    Синтаксический анализатор / парсер

    Список токенов проходит через парсер и превращается в дерево.

    Следующая стадия — парсер. Он преобразует исходный текст, то есть список токенов (с учётом скобок и порядка операций), в абстрактное синтаксическое дерево, которое позволяет структурно представить правила создаваемого языка. Сам по себе процесс можно назвать простым, но с увеличением количества языковых конструкций он сильно усложняется.

    Bison

    На этом шаге я также думал использовать стороннюю библиотеку, рассматривая Bison для генерации синтаксического анализатора. Он во многом похож на Flex — пользовательский файл с синтаксическими правилами структурируется с помощью программы на языке C. Но я снова отказался от средств автоматизации.

    Преимущества кастомных программ

    С лексером моё решение писать и использовать свой код (длиной около 200 строк) было довольно очевидным: я люблю задачки, а эта к тому же относительно тривиальная. С парсером другая история: сейчас длина кода для него — 750 строк, и это уже третья попытка (первые две были просто ужасны).

    Тем не менее, я решил делать парсер сам. Вот основные причины:

    • минимизация переключения контекста;
    • упрощение сборки;
    • желание справиться с задачей самостоятельно.

    В целесообразности решения меня убедило высказывание Уолтера Брайта (создателя языка D) в одной из его статей:

    Я бы не советовал использовать генераторы лексических и синтаксических анализаторов, а также другие так называемые «компиляторы компиляторов». Написание лексера и парсера не займёт много времени, а использование генератора накрепко привяжет вас к нему в дальнейшей работе (что имеет значение при портировании компилятора на новую платформу). Кроме того, генераторы отличаются выдачей не релевантных сообщений об ошибках.

    Абстрактный семантический граф

    Переход от синтаксического дерева к семантическому графу

    В этой части я реализовал структуру, по своей сути наиболее близкую к «промежуточному представлению» (intermediate representation) в LLVM. Существует небольшая, но важная разница между абстрактным синтаксическим деревом (АСД) и абстрактным семантическим графом (АСГ).

    АСГ vs АСД

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

    Запуск

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

    Варианты компиляции

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

    Написать свой компилятор

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

    LLVM — это коллекция инструментов для компиляции, которой пользуются, например, разработчики Swift, Rust и Clang. Я решил остановиться на этом варианте, но опять не рассчитал сложности задачи, которую перед собой поставил. Для меня проблемой оказалось не освоение ассемблера, а работа с огромной многосоставной библиотекой.

    Транспайлинг

    Мне всё же нужно было какое-то решение, поэтому я написал то, что точно будет работать: транспайлер (transpiler) из Pinecone в C++ — он производит компиляцию по типу «исходный код в исходный код», а также добавил возможность автоматической компиляции вывода с GCC. Такой способ не является ни масштабируемым, ни кроссплатформенным, но на данный момент хотя бы работает почти для всех программ на Pinecone, это уже хорошо.

    Дальнейшие планы

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

    Заключение

    Надеюсь, эта статья окажется кому-нибудь полезной. Я крайне рекомендую хотя бы попробовать написать свой язык, несмотря на то, что придётся разбираться во множестве деталей реализации — это обучающий, развивающий и просто интересный эксперимент.

    Вот общие советы от меня (разумеется, довольно субъективные):

    • если у вас нет предпочтений и вы сомневаетесь, компилируемый или интерпретируемый писать язык, выбирайте второе. Интерпретируемые языки обычно проще проектировать, собирать и учить;
    • с лексерами и парсерами делайте, что хотите. Использование средств автоматизации зависит от вашего желания, опыта и конкретной ситуации;
    • если вы не готовы / не хотите тратить время и силы (много времени и сил) на придумывание собственной стратегии разработки ЯП, следуйте цепочке действий, описанной в этой статье. Я вложил в неё много усилий и она работает;
    • опять же, если не хватает времени / мотивации / опыта / желания или ещё чего-нибудь для написания классического ЯП, попробуйте написать эзотерический, типа Brainfuck. (Советуем помнить, что если язык написан развлечения ради, это не значит, что писать его — тоже сплошное развлечение. — прим. перев.)

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

    О том, что ввязался в историю с созданием Pinecone, ни в коем случае не жалею — это отличный эксперимент, и он только начался.

    Компилятор

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

    Закономерен так же вопрос: а почему, собственно, компилятор, а не интерпретатор? Обоснование этого выбора — в статье Философия языка.

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

    Что ещё почитать на эту тему

    Опубликовано: 2012.09.25, последняя правка: 2020.10.29 15:54

    Отзывы

    Закономерен так же вопрос: а почему, собственно, компилятор, а не интерпретатор? Или что-то ещё, сочетающее в себе и то, и другое — типа Форта? Наверное, всё-таки исполняемый код всё-таки более предпочтителен во многих отношениях. Но к этой теме ещё вернёмся.

    Это зависит от направления использования языка. Так-то лидеры Ява и C# вообще-то интерпретаторы. Ну или что-то среднее. Ну никак не компиляторы. Конечно есть интерпретаторы языка Си как и компиляторы Бейсика, но реализация трансляторов как правило исходит от практического применения — где, когда и как это будет использоваться. Сейчас многие «традиционные» системы из-за конкуренции с интерпретацией вынуждены уметь генерировать код под разные платформы. Например последние изменения Делфи. Лазарус и Code Typhoon например умеют транслировать код под всякую экзотику, хоть под BeOs. Под Андроид уже не компилирует только самый ленивый, а все из-за конкуренции с кроссплатформенным Ява (который по сути развил идеи P-кода Паскаля). 1С тоже ни рыба, ни мясо, а неведома зверушка (хотя производитель гордо говорит о компиляции).

    2020/04/15 13:27, Автор сайта #

    Теперь есть философия языка, поэтому этот вопрос можно закрыть. Но во что компилировать? Очень перспективна LLVM, но пока неясно, как реализовать некоторые неочевидные моменты. Существует код для Intel x86, но непонятно, что должно ему соответствовать в LLVM.

    Написание компилятора на своем родном языке

    Интуитивно, кажется, что компилятор для языка Foo сам не может быть записан в Foo. Более конкретно, первый компилятор для языка Foo не может быть записан в Foo, но любой последующий компилятор может быть записан для Foo .

    Но действительно ли это так? У меня есть очень смутное воспоминание о том, как читать язык, чей первый компилятор был написан в «самом себе». Возможно ли это, и если да, то как?

    Это называется «начальной загрузкой». Сначала вы должны создать компилятор (или интерпретатор) для своего языка на каком-то другом языке (обычно Java или C). Как только это будет сделано, вы можете написать новую версию компилятора на языке Foo. Вы используете первый компилятор bootstrap для компиляции компилятора, а затем используете этот компилируемый компилятор для компиляции всего остального (включая будущие версии самого себя).

    Большинство языков действительно созданы таким образом, частично потому, что языковые дизайнеры любят использовать язык, который они создают, а также потому, что нетривиальный компилятор часто служит полезным ориентиром для того, как «полный» язык может быть.

    Примером этого может быть Scala. Его первый компилятор был создан в Пицце, экспериментальном языке Мартина Одерского. Начиная с версии 2.0, компилятор был полностью переписан в Scala. С этого момента старый компилятор Pizza может быть полностью отброшен из-за того, что новый компилятор Scala может быть использован для компиляции для будущих итераций.

    Я вспоминаю прослушивание подкаста Software Engineering Radio, в котором Дик Габриэль говорил о начальной загрузке оригинального интерпретатора LISP, написав «чистую» версию на LISP на бумаге и вручную собрав ее в машинный код. С тех пор остальные функции LISP были написаны и интерпретированы с помощью LISP.

    Добавление любопытства к предыдущим ответам.

    Вот цитата из руководства Linux From Scratch, на шаге, где начинается сборка компилятора GCC из его источника. (Linux From Scratch — это способ установки Linux, который радикально отличается от установки дистрибутива тем, что вам нужно скомпилировать каждый отдельный двоичный файл целевой системы.)

    Цель bootstrap не просто компилирует GCC, но компилирует его несколько раз. Он использует программы, скомпилированные в первом раунд, чтобы скомпилировать себя во второй раз, а затем снова в третий раз. Затем он сравнивает эти второй и третий компилируется, чтобы убедиться, что он может воспроизводить себя безупречно. Это также означает, что он был скомпилирован правильно.

    Такое использование цели «bootstrap» мотивировано тем фактом, что компилятор, который используется для построения целевой системы, может не иметь ту же версию целевого компилятора. Поступая таким образом, вы обязательно получите в целевой системе компилятор, который может компилироваться сам.

    Когда вы пишете свой первый компилятор для C, вы пишете на другом языке. Теперь у вас есть компилятор для C, скажем, на ассемблере. В конце концов, вы придете к тому месту, где вам придется анализировать строки, особенно экранирующие последовательности. Вы напишите код для преобразования \n в символ с десятичным кодом 10 (и \r в 13 и т.д.).

    После того, как этот компилятор будет готов, вы начнете переопределять его в C. Этот процесс называетсяначальной загрузкой.

    Код разбора строки станет следующим:

    Когда он компилируется, у вас есть двоичный файл, который понимает ‘\n’. Это означает, что вы можете изменить исходный код:

    Так где же информация о том, что \n — это код для 13? Это в двоичном виде! Это похоже на ДНК: компиляция исходного кода C с этим двоичным файлом унаследует эту информацию. Если компилятор сам компилируется, он передает эти знания своим потомкам. С этого момента нет никакого способа увидеть из одного источника, что будет делать компилятор.

    Если вы хотите скрыть вирус в исходном коде какой-либо программы, вы можете сделать это следующим образом: получить исходный код компилятора, найти функцию, которая компилирует функции, и заменить ее следующим:

    Интересными частями являются A и B. A — это исходный код для compileFunction , включая вирус, вероятно, каким-то образом зашифрованный, так что это не очевидно из поиска в полученном двоичном файле. Это гарантирует, что компиляция с самим компилятором сохранит код внедрения вируса.

    B — то же самое для функции, которую мы хотим заменить нашим вирусом. Например, это может быть функция «login» в исходном файле «login.c», которая, вероятно, из ядра Linux. Мы могли бы заменить его версией, которая будет принимать пароль «joshua» для учетной записи root в дополнение к обычному паролю.

    Если вы скомпилируете это и распространите в виде бинарного файла, вы не сможете найти вирус, посмотрев на источник.

    КОМПИЛЯТОР

    Словарь иностранных слов, вошедших в состав русского языка.- Чудинов А.Н. , 1910 .

    Словарь иностранных слов, вошедших в состав русского языка.- Павленков Ф. , 1907 .

    Объяснение 25000 иностранных слов, вошедших в употребление в русский язык, с означением их корней.- Михельсон А.Д. , 1865 .

    Полный словарь иностранных слов, вошедших в употребление в русском языке.- Попов М. , 1907 .

    Новый словарь иностранных слов.- by EdwART, , 2009 .

    Большой словарь иностранных слов.- Издательство «ИДДК» , 2007 .

    Толковый словарь иностранных слов Л. П. Крысина.- М: Русский язык , 1998 .

    Смотреть что такое «КОМПИЛЯТОР» в других словарях:

    компилятор — См. писатель. Словарь русских синонимов и сходных по смыслу выражений. под. ред. Н. Абрамова, М.: Русские словари, 1999. компилятор автор, писатель; транслятор, халтурщик, программа Словарь русских синонимов … Словарь синонимов

    Компилятор — программа, преобразующая текст, написанный на алгоритмическом языке, в программу, состоящую из машинных команд. Компилятор создает законченный вариант программы на машинном языке. См. также: Трансляторы Финансовый словарь Финам … Финансовый словарь

    КОМПИЛЯТОР — КОМПИЛЯТОР, КОМПЬЮТЕРНАЯ ПРОГРАММА, которая переводит символы ЯЗЫКА ПРОГРАММИРОВАНИЯ в команды, которые может непосредственно воспринимать компьютер. Программы по большей части пишутся на ЯЗЫКАХ ВЫСОКОГО УРОВНЯ, таких как «Си», Паскаль или Бейсик … Научно-технический энциклопедический словарь

    КОМПИЛЯТОР — КОМПИЛЯТОР, компилятора, муж. (книжн.). Автор компиляции. || Литератор, способный писать только компиляции (пренебр.). Жалкий компилятор. Толковый словарь Ушакова. Д.Н. Ушаков. 1935 1940 … Толковый словарь Ушакова

    компилятор — а, м. compilateur <, лат. compilator. Автор компиляции, лицо, занимающееся компиляцией (заимствованием материалов, изложением результатов чужих трудов без самостоятельной обработки источников). БАС 1. Собирающий из разных сочинений в одно;… … Исторический словарь галлицизмов русского языка

    КОМПИЛЯТОР — (англ. compiler от compile составлять компилировать), в информатике то же, что транслятор … Большой Энциклопедический словарь

    КОМПИЛЯТОР — КОМПИЛЯТОР, а, муж. (книжн.). Человек, к рый занимается компиляцией. | жен. компиляторша, и (разг.). | прил. компиляторский, ая, ое. Толковый словарь Ожегова. С.И. Ожегов, Н.Ю. Шведова. 1949 1992 … Толковый словарь Ожегова

    КОМПИЛЯТОР — (compiler) Компьютерная программа, переводящая программу, написанную на языке высокого уровня (high level language), в подробные команды (называемые машинным кодом (machine code), которые компьютер может выполнить. Программа должна быть… … Словарь бизнес-терминов

    компилятор — Программа или техническое средство, выполняющие компиляцию. [ГОСТ 19781 90] Тематики обеспеч. систем обраб. информ. программное EN compiler … Справочник технического переводчика

    Компилятор — в вычислительной технике, то же, что транслятор. … Иллюстрированный энциклопедический словарь

    Слово компилятор

    Слово состоит из 10 букв: первая к, вторая о, третья м, четвёртая п, пятая и, шестая л, седьмая я, восьмая т, девятая о, последняя р,

    Слово компилятор английскими буквами(транслитом) — kompilyator

    • Буква р встречается 1 раз. Слова с 1 буквой р
    • Буква т встречается 1 раз. Слова с 1 буквой т
    • Буква я встречается 1 раз. Слова с 1 буквой я
    • Буква и встречается 1 раз. Слова с 1 буквой и
    • Буква л встречается 1 раз. Слова с 1 буквой л
    • Буква к встречается 1 раз. Слова с 1 буквой к
    • Буква м встречается 1 раз. Слова с 1 буквой м
    • Буква п встречается 1 раз. Слова с 1 буквой п
    • Буква о встречается 2 раза. Слова с 2 буквами о

    Значения слова компилятор. Что такое компилятор?

    Компилятор Компилятоp (от англ. Compile — собирать вместе, составлять) — системная программа, выполняющая преобразование программы, написанной на одном алгоритмическом языке, в программу на языке, близком к машинному…

    КОМПИЛЯТОР — (compiler) Компьютерная программа, переводящая программу, написанную на языке высокого уровня (high-level language), в подробные команды (называемые машинным кодом…

    Компилятор Компилятор — программа, преобразующая текст, написанный на алгоритмическом языке, в программу, состоящую из машинных команд. Компилятор создает законченный вариант программы на машинном языке.

    КОМПИЛЯТОР, КОМПЬЮТЕРНАЯ ПРОГРАММА, которая переводит символы ЯЗЫКА ПРОГРАММИРОВАНИЯ в команды, которые может непосредственно воспринимать компьютер. Программы по большей части пишутся на ЯЗЫКАХ ВЫСОКОГО УРОВНЯ, таких как «Си», Паскаль или Бейсик…

    Научно-технический энциклопедический словарь

    Кросс-компиля́тор (англ. cross compiler) — компилятор, производящий исполняемый код для платформы, отличной от той, на которой исполняется сам кросс-компилятор. Такой инструмент бывает полезен, когда нужно получить код для платформы.

    Компилятор компиляторов — программа, воспринимающая синтаксическое или семантическое описание языка программирования и генерирующая компилятор для этого языка.

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

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

    Компиляторы: принципы, технологии и инструменты

    Компиляторы: принципы, технологии и инструменты — классический учебник по теории построения компиляторов под авторством Альфреда В. Ахо, Рави Сети и Джеффри Д. Ульмана, известный также как «Книга дракона».

    Примеры употребления слова компилятор

    Но как, ведь автор жития зачастую не столько писатель, сколько компилятор?

    Использовалась последняя версия Firefox Nightly, ORBX.js, ASM.js и компилятор Emscripten.

    Есть такая версия, что вот он такой великий компилятор, что он собрал музыку, которая вообще в мире существовала за всю эпоху.

    Версия Go 1.1 получила значительный прирост в производительности, более оптимизированный компилятор, линковщик и обновленные инструменты для разработчиков.

    Правда, компилятор работает несколько странно, он без проблем распознает обычные команды JavaScript, но при загрузке библиотеки Underscore простейший код вызова объекта, выводящего на экран текст «Мяу!»

    Можно ли написать компилятор в машиный код на языке очень высокого уровня?

    Можно ли написать компилятор в машиный код на языке очень высокого уровня?

    1. Поверьте человеку, который пишет на Си с 1985 года (30 лет, вроде бы?) — НИКОГДА не пишите на Си ничего, если только к вашему виску не приставили пистолет. Исключение одно — ядро ОС. Да и то.

    2. Что угодно можно написать на чём угодно. Вопрос удобства.

    3. Писать компилятор надо на языке с развитыми средствами поддержки жизни проекта. Таких два — Java и C#. Можно (а если Вам это комфортно, то и нужно) использовать функциональные расширения соответствующих платформ. Scala/F#.

    4. На говноязыках серьёзные вещи писать не нужно. Ключевое свойство говноязыка — обсуждение вокруг него о том, как бедные программеры перетрудились явно прописывать руками типы всех переменных. На таких ЯП можно писать затычки и примочки.

    5. Не применяйте генераторы лексических и грамматических анализаторов, пока не научитесь писать компилятор руками. Ключевое слово — парсинг рекурсивным спуском. Это реально просто, если грамматика языка — LR1. Для начала надо взять простой язык. Очень простой.

    6. Базовый компилятор с кодогенерацией для стековой машины нужно уметь писать за два дня. Если вы хотите это уметь.

    7. Бекэнды (реальную кодогенерацию) писать НЕ НУЖНО. Вообще. Вы её хорошо не напишете ни-ко-гда. Проще генерировать на выходе Си и докомпилировать приличным си-компилятором.

    Илон Маск рекомендует:  Как убрать панель на изображениях в Internet Explorer 6
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL