LINUX.ORG.RU
Ответ на: комментарий от emulek

а вот не добавлял-бы ½, тогда всё было чудесно

½ никуда не надо добавлять, оно там есть по определению. в нашем случае ½ = 2

jtootf ★★★★★
()
Ответ на: комментарий от buddhist

Дай тогда точное определение шитого кода

По своей сути, шитый код — это набор адресов для нерекурсивного (нестекового) вызова подпрограм, каждая из которых передаёт управление (классическое NEXT) следующей (потому и «шитый» — аналогия с нитками на швейной машинке).

Прямой — когда в блоке кода хранятся адреса процедур.

Косвенный — когда в блоке кода хранятся адреса ячеек CFA процедур (что позволяет более гибко управлять исполнением).

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

Для линейного выполнения шитого кода примитивов не нужен стек. Для исполнения подпрограммного — нужен.

Ну, и если грубо — при шитом коде работает «виртуальная машина» (при всей её примитивности), при подпрограммном — идёт обычное исполнение машинного кода.

KRoN73 ★★★★★
()
Ответ на: комментарий от buddhist

Да, ещё, вдогонку. Шитый код позволяет писать машиннонезависимый переносимый код, чем и пользовались в ряде Фортов (Из современных, DS, кажется? — x86/ARM). Подпрограммный, как легко понять, пишется только под одну архитектуру.

KRoN73 ★★★★★
()

компилятор компилирует, интерпретатор интерпретирует, а транслятор транслирует. чего тебе не ясно, гомис?

chg ★★★★★
()
Ответ на: комментарий от jtootf

½ никуда не надо добавлять, оно там есть по определению. в нашем случае ½ = 2

ну тогда мы возвращаемся к GF(3). При чём тут «добавим ½»?

emulek
()
Ответ на: комментарий от emulek

Давно не встречал такого четкого определения, кроме шуток!

Twissel ★★★★★
()
Ответ на: комментарий от Twissel

Просто, по-видимому устаревший материал из советских книжек.

В том-то и дело, что вся моя аргументация — из советских книжек :D И она описывает любые [которые мне пока попадались] сложные случаи. В отличии того, что пишут в Вики :)

KRoN73 ★★★★★
()
Ответ на: комментарий от anonymous

Хм, но тут вопрос. Ведь перед тем как выполнить программу ее нужно привести к соответствующему машинному представлению. Это разве не трансляция? Где ошибка?

Twissel ★★★★★
()
Ответ на: комментарий от KRoN73

В том-то и дело, что вся моя аргументация — из советских книжек

в советское время типичный интерпретатор обрабатывал команду за командой. А в наше время типичный же интерпретатор обрабатывает _весь_ текст целиком, делает явно/неявно что-то типа компиляции, а потом уже выполняет. Выше я приводил пруф с bash'ем.

Потому советские книжки ввели тебя в заблуждение. Покомандное исполнение уже давно никто не применяет, и в интерпретаторах тоже.

emulek
()
Ответ на: комментарий от Twissel

Хм, но тут вопрос. Ведь перед тем как выполнить программу ее нужно привести к соответствующему машинному представлению.

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

anonymous
()
Ответ на: комментарий от anonymous

Хорошо, раз уж я ввязался в этот тред, тогда продолжим. В конечном счете, ведь тот же интерпретатор выполняется на конкретном ЦП, а не в абстрактном математическом вакууме, ведь так? Что тогда представляют из себя команды интерпретатора с точки зрения центрального процессора ПК ?!!

А именно есть ли такое преобразование, которое переводит систему команд интерпретатора в систему команд CPU?

Вот в чем мой вопрос.

Twissel ★★★★★
()
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

ты бредишь: если нет, то как же этот код _исполняется_? Может ты хотел сказать «нельзя сопоставить заранее»? Ну да, такое есть. Ну и что?

PS: вот только что написал калькулятор, прям как в K&R. Там тоже интерпретация выражения вроде 2+2*2=?, выдаёт ессно 6. Да, какой именно код сопоставляется — от выражения зависит, и тем не менее, это всё на C++.

emulek
()
Ответ на: комментарий от emulek

как же этот код _исполняется_?

Исполняется код интерпретатора — он один на все интерпретируемые программы, которым ничего не соответствует кроме такого-то способа их исполнения этим интерпретатором.

Ну и что?

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

только что написал калькулятор

Теперь сделай функцию дампа своего машинного кода который «сопоставляется» в файл для любых выражений. Хотя погоди... тебе же придётся выкинуть свой интерпретатор и написать компилятор :)

quasimoto ★★★★
()
Ответ на: комментарий от Twissel

Что тогда представляют из себя команды интерпретатора с точки зрения центрального процессора ПК ?!!

Ничего не представляют.

А именно есть ли такое преобразование, которое переводит систему команд интерпретатора в систему команд CPU?

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

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

anonymous
()
Ответ на: комментарий от emulek

Может ты хотел сказать «нельзя сопоставить заранее»? Ну да, такое есть. Ну и что?

Ну и все. Нельзя данной интерпретируемой программе сопоставить конкретную последовательность команд. То есть перевода просто не существует.

если нет, то как же этот код _исполняется_?

Берет и исполняется. Для этого, к счастью, трансляция не требуется.

anonymous
()
Ответ на: комментарий от Twissel

А именно есть ли такое преобразование, которое переводит систему команд интерпретатора в систему команд CPU?

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

Ещё см. Чем отличается компилятор от интерпретатора? (комментарий) — мы можем на любую функцию смотреть как на интерпретатор (то же исполнение). Например, strlen (максимально упрощённый случай) притворяется функцией возвращающей 5 если на вход подаётся строка длинной в пять символов, 7 — семь символов и т.д. Какой код CPU соответствует strlen? Какой код CPU соответствует строке в пять символов?

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Исполняется код интерпретатора — он один на все интерпретируемые программы, которым ничего не соответствует кроме такого-то способа их исполнения этим интерпретатором.

да говорю же  — ты бредишь. Выполни $ while true; do true; done. Выполнил? И чем у тебя CPU загружен?

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

дык есть сопоставление. В любом интерпретаторе.

Теперь сделай функцию дампа своего машинного кода который «сопоставляется» в файл для любых выражений. Хотя погоди... тебе же придётся выкинуть свой интерпретатор и написать компилятор :)

чего «годить»? Могу и сопоставить. Каждая строка C++ кода порождает вполне конкретный машинный код. Если его сохранить, получится компилятор. Для каждого выражения получается свой код.

emulek
()
Ответ на: комментарий от anonymous

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

в таком случае, выполнить её на IA-32/amd64 тоже невозможно.

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

да, конечно.

emulek
()
Ответ на: комментарий от anonymous

Может ты хотел сказать «нельзя сопоставить заранее»? Ну да, такое есть. Ну и что?

Ну и все. Нельзя данной интерпретируемой программе сопоставить конкретную последовательность команд. То есть перевода просто не существует.

с какого перепугу перевод обязан быть однозначным? Ещё раз, для тех кто в танке: обычный цикл выполняется неизвестно сколько раз. Рекурсия выполняется неизвестно сколько раз. Вот у меня например для выражения 1+2+3 две команды add, а для 1+2+3+4 четыре команды add. И что? Код один.

если нет, то как же этот код _исполняется_?

Берет и исполняется

ага. Благодатный огонь снизошёл.

emulek
()
Ответ на: комментарий от anonymous

то есть перевести в какой-то программный код.

машинный код selffix

Дзен-программа с фекспрами.

tailgunner ★★★★★
()
Ответ на: комментарий от emulek

Выполнил? И чем у тебя CPU загружен?

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

дык есть сопоставление.

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

А в случае компилятора — свой код для каждой программы.

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

Могу и сопоставить.

Ну выкатывай код.

Каждая строка C++ кода порождает вполне конкретный машинный код.

Так ты калькулятор или интерпретатор C++ написал?

quasimoto ★★★★
()
Ответ на: комментарий от emulek

Это код интерпретатора. Теперь показывай код CPU в виде инструкций соответствующий его интерпретируемым программам, то есть строкам — «12345», например (5 при интерпретации).

quasimoto ★★★★
()
Ответ на: комментарий от anonymous

Но конкретно в момент исполнения команд на ЦП эта последовательность задана и однозначна, они же машинные, если программа работает. Иначе такой интерпретатор это сферический конь Бора в вакууме :)

Twissel ★★★★★
()
Ответ на: комментарий от emulek

ага. Благодатный огонь снизошёл.

Аналогия близка к действительности. Без пруфов, дальнейшая дискуссия бессмысленна

Twissel ★★★★★
()
Ответ на: комментарий от quasimoto

которым ничего не соответствует кроме такого-то способа их исполнения этим интерпретатором.

Ну здесь мы все будем единодушны им соответствует их собственный исходный код.

Мне бы такое зрение увидеть никого, да еще на таком расстоянии (с)

Белый Король. Алиса в Зазеркалье

Twissel ★★★★★
()
Ответ на: комментарий от Twissel

То есть «SELECT foo FROM bar WHERE baz» соответствует не что иное, как «SELECT foo FROM bar WHERE baz»?

Это прямо архи полезно для знания семантики этого языка :)

Либо ей соответствует интерпретатор, точнее один из способов его выполнения, http://en.wikipedia.org/wiki/Operational_semantics, со своим смыслом, http://en.wikipedia.org/wiki/Denotational_semantics.

Или другая программа с эквивалентной семантикой, http://homepage.cs.uri.edu/faculty/hamel/courses/2011/fall2011/csc501/lecture..., http://homepage.cs.uiowa.edu/~slonnegr/plf/Book/Chapter7.pdf, и своим смыслом.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

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

Так что приплетать сюда исчисление кортежей, как аргумент, несколько излишне.

Twissel ★★★★★
()
Ответ на: комментарий от Twissel

Нет подмены понятий, есть понятия языков, грамматик (это к синтаксису), трансляторов, интерпретаторов (это к соответствующим семантикам), это общие понятия. SQL — пример (никаких исчислений кортежей не подразумевалось), Си — пример, как и любые другие языки, будь то DSL или ЯП общего назначения.

И вообще я уже не знаю что мы обсуждаем.

Для си есть трансляция в машинный код? Ну да, поэтому существует и практикуется компиляция (или наоборот :)). Взаимно-однозначное? Нет, поэтому декомпиляция это гораздо более сложная задача и практикуется обратная разработка как поиск её решения. Каким боком это к теме?

Ещё раз ссылки, по мелочи:

http://en.wikipedia.org/wiki/Formal_language

http://en.wikipedia.org/wiki/Formal_grammar

http://en.wikipedia.org/wiki/Interpreter_(computing)

http://en.wikipedia.org/wiki/Translator_(computing) (предложение про интерпретатор проясняется дальше)

http://en.wikipedia.org/wiki/Operational_semantics

http://en.wikipedia.org/wiki/Denotational_semantics

Точнее (загугли pdf-ки):

http://www.amazon.com/Compilers-Principles-Techniques-Tools-Edition/dp/032148...

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

Более новые, там так же, я выше по треду цитировал:

http://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262...

http://www.amazon.com/Programming-Language-Pragmatics-Third-Edition/dp/012374... (конкретно тут проясняется про интерпретатор в смысле википедии)

http://www.amazon.com/Design-Concepts-Programming-Languages-Franklyn/dp/02622...

Ещё:

http://homepage.cs.uiowa.edu/~slonnegr/plf/Book/Chapter7.pdf

http://homepage.cs.uri.edu/faculty/hamel/courses/2011/fall2011/csc501/lecture...

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

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

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

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

Есть код интерпретатора, один. Интерпретируемые выражения соответствуют путям исполнения этого кода, одного и того же. А в случае компилятора — свой код для каждой программы.

x+y всегда транслируется компилятором в команду add, и интерпретатором тоже(если без оптимизации конечно). Не вижу разницы в упор.

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

всё там прекрасно вытаскивается.

Ну выкатывай код.

не понимаю, код чего?

Ну возьми gdb и посмотри.

Так ты калькулятор или интерпретатор C++ написал?

калькулятор, который транслирует ЯП арифметических выражений(а это тоже алгоритмический ЯП) в машинный код, и его сразу выполняет. При чём тут C++? Кто вообще сказал, что программа на C++ должна обязательно компилироваться в C++, а уж потом в ассемблер? Мой калькулятор вообще никакого отношения к C++ не имеет, у него на входе арифметическое выражение, а на выходе машинный код, который прямо сразу и выполняется. И сам он на машинном коде, а на C++ только его исходник, который можно на что угодно переписать.

И да, скобки мой калькулятор умеет, а следовательно там есть «мощный eval». Как вы и заказывали.

emulek
()
Ответ на: комментарий от quasimoto

Это код интерпретатора. Теперь показывай код CPU в виде инструкций соответствующий его интерпретируемым программам, то есть строкам — «12345», например (5 при интерпретации).

это машинный код. Для любых ASCIIZ строк(ну в смысле <2³¹). Для «12345» оно тоже работает(правда там 6 итераций).

emulek
()
Ответ на: комментарий от quasimoto

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

декомпиляция очень простая задача на самом деле. Вот только код после декомпиляции невозможно читать людям. Но это не относится к нашему спору.

И да, именно взаимно-однозначное существует. Просто людям неудобно им пользоваться. Мне проще писать ⅔x, а компилятор переделывает это в x*0xAAAAAAAA. Также мне нравится использовать все три типа циклов (for, while, do{}while), но компилятор юзает только последний тип. Ну а ещё компилятор через строку пихает goto, и прочую гадость. А мне так читать неудобно.

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

1. эквивалентен моему коду

2. взаимо-однозначен

ссылки

ты путаешь подходы и определения. Формально компилятор и интерпретатор ничем не отличается, однако для построения удобного и годного DSL важно учитывать специфику. Т.е. в принципе можно запихать замкнутый eval в C→C, вот только оно нафиг никому не нужно. Сам ЯП заточен не компиляцию в машинный код. Также и введение оптимизируещего компилятора в какой-нить PHP тоже ничего не даст и не нужно. Компилятор всё равно не сможет оптимизировать утиную типизацию, которая определиться только в рантайме. Вот и будет на массив char'ов в 10 штук, хранить и пережёвывать 20 указателей в 8 char'ов каждый. Смысл?

emulek
()
Ответ на: комментарий от emulek

цикл транслируется в команды CPU, которые и выполняются.

Цикл у тебя сразу выполняется в случае pure interpretation. Команды CPU у тебя уже тут, в коде откомпилированного интерпретатора, его бинарника, он берёт твой текст/AST и делает своё дело как любая другая функция — нечего ему транслировать, так как выходного языка не предполагается.

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

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

x+y всегда транслируется компилятором в команду add, и интерпретатором тоже(если без оптимизации конечно).

Да ладно, во что хочет, в то и транслируется, как хочет, так и интерпретирует, то что в C++ _+_ не имеет отношения к тому что в реализуемом языке _+_ (gmp_add или matrix_add, например) — поскипано во имя перегрузки.

Не вижу разницы в упор.

Ты просто привязался к своему «интерпретатор транслирует свои программы в инструкции CPU и выполняет их», хотя привязываться не нужно — нужно коммуницировать :)

То есть ты говоришь, что

void f(int n) {
    ...
    if (n == 2) {
        ... block ...
    }
}

транслирует (во время выполнения, чо) вход 2 в CPU инструкции block. Они полученные уже, правда, заранее компиляцией этого кода, да и не работает это — сделай block не локальным, но нетривиальным control flow и непонятно где твоё соответствие (в формальном смысле этого слова, то есть отображения из язык в язык, а то может ты «примерно» говоришь).

всё там прекрасно вытаскивается.

Ну возьми gdb и посмотри.

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

При чём тут C++?

Ты говоришь

Каждая строка C++ кода порождает вполне конкретный машинный код.

А тебе надо, чтобы каждое арифметическое выражение транслировалось в машинный код (раз всё вытаскивается). Т.е. я тебе даю, например, (2+3)*5 — твой велосипед мне кидает кусок ассемблера/машинного кода, а если ты интерпретируешь, то нечего рассказывать, ты путаешь код самого интерпретатора с кодом который бы соответствовал (2+3)*5 при компиляции.

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

Да, я уже понял что ты пишешь, «у меня на входе strlen строки, а на выходе машинный код [который ты в виде *.s уже запостил], который прямо сразу и выполняется».

это машинный код. Для любых ASCIIZ строк

Ну то есть транслятора из строк в CPU код у тебя нет, я и говорю, что strlen это вырожденный пример интерпретатора (и транслятора, если говорить о трансляции в чистые значения, то есть о constant folding).

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от emulek

Но это не относится к нашему спору.

Это относится к тому, что compile/decompile не «взаимно-однозначны» — это сложно и невозможно, если только на классах эквивалентности modulo сохранению семантики — это возможно и легко, но не интересно и есть вопрос о том что есть сохранение семантики.

взаимно-однозначное существует

То есть ты можешь скомпилировать программу, потом декомпилировать её обратно и получить ту же программу?

Вот только код после декомпиляции невозможно читать людям

Нет, значит не взаимно-однозначное, если тебе не пофиг на читаемость и сохранение абстракций и не нужно только «работает так же» (да и то, не факт, что компиляция с оптимизациями, декомпиляция и повторная компиляция с оптимизациями будет «так же» работать).

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

А пруф? А то пишуть альтёрнатив апроач.

Но правда, что и то и другое можно объединить под общим «processing», «обработка».

З.Ы. в математике, тащемто, интерпретация и трансляция (гомоморфизм) это примерно то же, что эти понятия по ссылкам.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от quasimoto

Цикл у тебя сразу выполняется в случае pure interpretation. Команды CPU⁽¹ у тебя уже тут, в коде откомпилированного интерпретатора, его бинарника, он берёт твой текст/AST и делает своё дело как любая другая функция — нечего ему транслировать⁽², так как выходного языка не предполагается.

т.е. ты утверждаешь, что (1 берётся из хрустального шара или другой магией(благодатным огнём), да?

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

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

выкидывать ничего не нужно. Не передёргивай мои слова.

x+y всегда транслируется компилятором в команду add, и интерпретатором тоже(если без оптимизации конечно).

Да ладно, во что хочет, в то и транслируется, как хочет, так и интерпретирует, то что в C++ _+_ не имеет отношения к тому что в реализуемом языке _+_

ЯП и его стандарт не имеет. Однако компилятор в IA-32 других вариантов не знает. Как и интерпретатор. И не приплетай сюда перегрузку, она меняет сам смысл operator+(). Речь лишь про встроенный тип int/float. Я уже говорил выше, что если у тебя «утиная» типизация, то что компилятор, что интерпретатор, могут только в рантайме решить, каким кодом складывать числа. Посему тащат за собой всё множество кодов для любых сложений.

Ты просто привязался к своему «интерпретатор транслирует свои программы в инструкции CPU и выполняет их», хотя привязываться не нужно — нужно коммуницировать :)

просто это реальность такая, чудес не бывает.

транслирует (во время выполнения, чо) вход 2 в CPU инструкции block. Они полученные уже, правда, заранее компиляцией этого кода, да и не работает это — сделай block не локальным, но нетривиальным control flow и непонятно где твоё соответствие (в формальном смысле этого слова, то есть отображения из язык в язык, а то может ты «примерно» говоришь).

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

Ну возьми gdb и посмотри.

Это не вытаскивается, это каша

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

Т.е. я тебе даю, например, (2+3)*5 — твой велосипед мне кидает кусок ассемблера/машинного кода, а если ты интерпретируешь, то нечего рассказывать, ты путаешь код самого интерпретатора с кодом который бы соответствовал (2+3)*5 при компиляции.

вот «код самого интерпретатора» и есть выход. Этот код может вычислить (2+3)*5, и дать ответ 25. Т.о. данный код является трансляцией любого выражения в машинный код, даже если само выражение заранее неизвестно. Как видишь, условие известности алгоритмов не обязательно. Алгоритм можно задать во время выполнения. Т.е. можно 2+(3*5), а можно (2+3)*5. Тут числа одинаковые, но алгоритм вычисления разный. Ответ тоже разный. Но интерпретатор один единственный, хотя машинный код порождается и выполняется разный.

Да, я уже понял что ты пишешь, «у меня на входе strlen строки, а на выходе машинный код [который ты в виде *.s уже запостил], который прямо сразу и выполняется».

у тебя тоже.

Ну то есть транслятора из строк в CPU код у тебя нет, я и говорю, что strlen это вырожденный пример интерпретатора (и транслятора, если говорить о трансляции в чистые значения, то есть о constant folding).

почему нет? Ок, напишу:

if(strcpy(input_string, "strlen")==0)
    fwrite(мой_код, размер_кода, 1, выходной_файл);
осталось сделать преобразование кода x в адрес определённой ячейки памяти. И компилятор готов. А если этого не делать, а просто занести x в edx, и выполнить мой код, то получится интерпретатор.

Ну то есть транслятора из строк в CPU код у тебя нет

зачем тебе такой транслятор? Что тебе мешает хранить строки как наборы байт? Зачем тебе их транслятор?

emulek
()
Ответ на: комментарий от quasimoto

То есть ты можешь скомпилировать программу, потом декомпилировать её обратно и получить ту же программу?

я на C/C++ — нет. Но теоретический такой код возможен и такой компилятор тоже. Просто оно никому не нужно. Если я пишу ⅔, то компилятор это превращает в 0x55555556, откуда ты ⅔ уже не вытащишь однозначно. Если я пишу x*=2, компилятор пишет x<<=1. Это тоже обратно переводится в x<<=1.

Нет, значит не взаимно-однозначное, если тебе не пофиг на читаемость и сохранение абстракций и не нужно только «работает так же»

при чём тут читаемость? Возможность есть. Просто она никому не нужна. Проще исходник приложить. Потому никто и не реализовал.

да и то, не факт, что компиляция с оптимизациями, декомпиляция и повторная компиляция с оптимизациями будет «так же» работать

ну дык с оптимизацией оно и так «не так» работает. А быстрее. Т.е. это не баг, а фича. Если я пишу 1+2, компилятору плевать на однозначность, и он пишет 3, откуда естественно не вытащить 1+2. Неужели ты думаешь, что невозможно написать такой компилятор, который будет в рантайме Over9000 раз складывать 1+2? Ради вселенской однозначности...

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

А пруф?

пруф — возможность исполнения и того и того в семантике одного и того же CPU. Потому что в CPU нет «двух режимов», а есть только один — исполнение кода. Потому, хоть в лоб, хоть полбу, если написано x+y, то это надо перевести в add.

emulek
()
Ответ на: комментарий от emulek

т.е. ты утверждаешь, что (1 берётся из хрустального шара или другой магией(благодатным огнём), да?

Чем отличается компилятор от интерпретатора? (комментарий)

A.

a program written in a source language S is directly executed by an S-interpreter, which is a program written in an implementation language

⁽¹ тебе по большому счёту не нужно, так как у тебя есть S-интерпретатор, который на своём уровне абстракций выполняет свои программы без всяких CPU. Сравни, допустим, с интерфейсом к файловым системам — ты можешь работать с ним как с API не зная ничего про архитектуру, код CPU, драйвера или ОС, тебе это не интересно на этом уровне. Есть представление о семантике implementation language и ладно — дальше нам не нужно.

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

(S-terms -> S-Machine) by S-interpreter

B.

Но если хочешь — пусть S-интерпретатор написан на своём языке Inter и может быть скомпилирован в язык CPU компилятором Inter -> CPU, это будет ⁽², язык CPU может быть выполнен CPU-интерпретатором — вот это уже ⁽¹. Интерпретация это семантическая обработка, с ней связан абстрактный вычислитель, то есть в случае S-интерпретатора совсем абстрактный, в случае CPU — и конкретный тоже.

(S-terms -> S-Machine) by S-interpreter

(Inter-terms -> CPU-terms) by Inter-to-CPU compiler for this particular S-interpreter

(CPU-terms -> CPU-machine) by CPU-interpreter

C.

In the translation approach, an S program is translated to a program in the target language T, which can be executed by a T-interpreter.

Чистый интерпретатор не делает S-terms -> T-terms, он берёт S, загружает в вычислитель и запускает его — S-terms -> S-machine. То есть с одной стороны у нас трансляция — синтаксическая обработка в виде чёрного ящика который работает как функция (http://en.wikipedia.org/wiki/Natural_transformation, http://en.wikipedia.org/wiki/Homomorphism, гомоморфизмы синтаксических структур из синтаксических категорий с естественностью по отношению к модельным функторам в семантические домены, то есть вообще говоря синтаксическая трансляция учитывает сохранение семантики), то есть принимает программы (синтаксис) и возвращает программы (он же), а с другой интерпретация — семантическая в виде ящика который работает как исполнитель/машина которая просто принимает программы и их выполняет (семантика, http://en.wikipedia.org/wiki/Functor, http://en.wikipedia.org/wiki/Interpretation_(logic), модели, семантические домены).

Речь лишь про встроенный тип int/float.

Сделай block не локальным, и код будет находится в другом месте.

Т.е. можно 2+(3*5), а можно (2+3)*5.

Ты как-то в сторону и на частности опять. Код не будет нигде находиться — см. A. выше. Но если берёшь B., то не путай и пойми простую вещь — терму S не соответствует CPU-терм (в ситуации к конкретно написанным (Inter-терм) и скомпилированным в конкретный CPU-терм интерпретатором), ему соответствует конкретный пробег CPU-машины/интерпретатора. Попросту говоря, block не будет в другом месте (это же тоже локально), он будет кусками размазан где попало, то есть это не конкретные инструкции, а нетривиальные отношения на них — вытащить их во что-то вменяемое не тривиально, поэтому компиляция отличается от интерпретации.

просто это реальность такая, чудес не бывает.

Да никакая «это» не «реальность» :)

вот «код самого интерпретатора» и есть выход.

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

Ок, напишу

Не так. Принимаешь source программу, то есть строку, во время компиляции вычисляешь её длину n и генерируешь target программу ret n. Это будет правильное продолжение аналогии.

зачем тебе такой транслятор?

Это пример.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 2)
Ответ на: комментарий от emulek

с какого перепугу перевод обязан быть однозначным?

При чем тут однозначность? Его просто нет. Мы никак не можем перевести. Ни однозначно, ни многозначно. Вообше никак.

Ещё раз, для тех кто в танке: обычный цикл выполняется неизвестно сколько раз. Рекурсия выполняется неизвестно сколько раз.

И что?

anonymous
()
Ответ на: комментарий от emulek

дык есть сопоставление. В любом интерпретаторе.

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

anonymous
()
Ответ на: комментарий от emulek

в таком случае, выполнить её на IA-32/amd64 тоже невозможно.

Возможно. Выполняют ведь.

да, конечно.

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

anonymous
()
Ответ на: комментарий от Twissel

да, конечно.

Любая виснущая программа, например :) Ей никакого машинного кода при интерпретации соответствовать не может (т.к. выполняется по факту бесконечная последовательность команд), но однако она прекрасно интерпретируется :)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.