Нужно ли писать свой компилятор? [закрыт]

Нужно ли писать свой компилятор? [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.

Закрыт 4 года назад .

Не могу понять, в чем сложность написания компилятора и нужно ли его вообще писать? Разве нет универсального компилятора - типа нажал "импорт" и все автоматически перевелось в машинный язык. Вопрос возник, потому что в интернете много противоречивой информации на этот счет.

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

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

Также в интернете пишут, что компилируемые языки сложнее интерпретируемых, потому что после написания программы на компилируемых языках ее нужно компилировать? А в чем сложность? Если я правильно понимаю, то уже давно существует соответствие команд высокого уровня битовой последовательности низкого (разумеется для каждого языка свое соответствие)? Или все совсем не так, тогда что из себя технически представляет компилирование на языке высокого уровня?

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

Насколько я понимаю компилятор нужен, чтобы преобразовать какую-нибудь программу на языке высокого уровня (например С "си") в машинный код, который понимает процессор.

Это верно, обычно так это и есть. (Исключение — компиляторы в промежуточный код, например, компилятор C#.)

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

Да. И вот именно переводом инструкций высокого уровня в инструкции низкого уровня и занимается компилятор.

Разве в языках программирования высокого уровня нет грубо говоря "программы перевода" на низкий уровень, называемый компиляцией?

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

Для того, чтобы было понятно, что задача компиляции сложна, представьте себе такую простую вещь, как нахождение всех деклараций переменных в файле с исходником на C++. Для этого вам придётся пробежаться препроцессором, и раскрыть все макросы (каждый из них может менять смысл кода). Затем, вам нужно пробежаться по тексту, и найти все идентификаторы. Все они переменные? Как бы не так, некоторые уже могут быть определены. Окей, ваш код нашёл строчку

Это определение указателя t на тип T ? Может, да, а может, нет. Если T и pt — ранее определённые переменные, то это вызов оператора умножения. То есть ваш код должен знать, какие переменные есть к текущему моменту, чтобы понять, является ли данная строчка объявлением новой переменной. А значит, должен знать границы всех функций и всех классов.

Затем, допустим, что у нас есть * , и мы выяснили, что это не объявление указателя, а умножение. Какую инструкцию для него использовать? Если это умножение целых чисел, на интеловской архитектуре можно использовать imul . Если это умножение чисел с плавающей запятой, вам понадобится команда наподобие mulsd (если вы используете XMM-регистры). А если одно из чисел с плавающей запятой, а другое целое, то такой команды умножения у процессора вовсе нет, и вам нужно сконвертировать целое число в число с плавающей точкой. А если у вас перемножаются не числа, а пользовательские структуры данных с перегруженным оператором умножения, то вместо умножения надо и вовсе вызвать функцию.

То, что я описал, не представляет собой и десятой доли процента сложности компилятора C++.

по идее писать ничего не надо (все уже должно быть 30 лет назад написано)?

Новые стандарты языков и новые языковые возможности выходят регулярно, в C#, например, только в этом году вышло три (минорных) версии языка. Старым компилятором невозможно скомпилировать новый код.

Если я правильно понимаю, то уже давно существует соответствие команд высокого уровня битовой последовательности низкого (разумеется для каждого языка свое соответствие)?

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

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

📎📎📎📎📎📎📎📎📎📎