как я понял, n это то, что в eval'е? Тогда из входных данных.
«Программой» называется текст определенного вида. «текстом» называется конечная последовательность символов определенного языка. КОНЕЧНАЯ. Бесконечная последовательность символов не является ни текстом, ни программой.
что ты так прицепился-то к бесконечности: вот тебе ОДНА команда: L: JMP L
Нет, это не правда. Сколько можно уже? В куче языков есть термы, которые ни в какое количество фиксированных машинных команд не транслируются. Даже в той же сишке.
Нету никаких входных данных. N - максимальное решение уравнения.
ну не тупи: «входные данные» это то, что внутри eval'а. Когда евал евалит, он из одного решения делает другое, и опять его в себя засовывает. Как змея, которая жрёт свой хвост.
И что? Речь идет о том, когда код бесконечен. В данном случае он конечен вполне.
код (вход и выход eval'а) потенциально бесконечен. IRL можешь юзать mmap(2), и отобразить в память всё свободное место на своём HDD. А код обрабатывающий сам eval — вполне конечен, и не очень большой.
При чтении терма <цифра> это число пишется в *sp, а потом sp увеличивается на 1. При чтении терма <операция> выполняется операция над предыдущим(-1) и пре-предыдущим(-2), а затем sp уменьшается на 1. При этом результат пишется в (-2) который после уменьшения sp становится (-1).
Можно сделать и обычную нотацию, как в школе. Но тогда потребуется хранить в стеке и операции тоже, т.к. операции нельзя будет выполнять сразу, например 2+2*2.
x[i] это сахар для *(x + i), так что если x указывает куда-то в середину массива, то x[0], *x это текущий элемент, x[1], *(x + 1) — следующий, x[-1], *(x - 1) — предыдущий и т.п.
Че то не совсем понятно твое определение. Есть read-eval-print-loop. Ничего он в себя не засовывает, он ждет входа.
тогда всё тупо и примитивно. Пример на сишечке выше.
А вот если у тебя eval порождает код, и потом опять этот код выполняет, то несколько сложнее: этот хитрый eval нужно с собой тащить. Т.е. компилятор встретив такой eval должен запихать в выходной код реализацию eval'а. Т.е. самого себя.
Во-первых, константа не является командой машкода. Во-вторых, я не спрашивал какой машкод соответствует «1+2;», я спрашивал что соответствует терму «1» и «+»
Все очень просто. Допустим у тебя есть интерпретатор Х, который интерпретирует некоторую программу. Емулек говорит: берем эту некоторую программу и кладем ее текст в память. Теперь генерируем код, который вызывает ф-ю евал интерпретатора Х на этой программе. Получившуюся хуету он называется «скомпилированной программой».
Все очень просто. Допустим у тебя есть интерпретатор Х, который интерпретирует некоторую программу. Емулек говорит: берем эту некоторую программу и кладем ее текст в память. Теперь генерируем код, который вызывает ф-ю евал интерпретатора Х на этой программе. Получившуюся хуету он называется «скомпилированной программой».
Ну так получившаяся программа будет текстом на языке интерпретатора X? Ее же обратно же надо скомпилировать будет или как? А как он скомпилирует то, что заранее не известно? Надо тогда, чтобы выхлоп интерпретатора X был корректным текстом на языке компилятора?
А так, он получит тока выхлоп интерпретатора X, больше ни хрена.
Да чо ты фантазируешь? Eval — это обычная функция, по сути.
да, обычная. Если у нас интерпретатор. А если у нас компилятор, то мы не сможем скомпилировать eval, т.к. не знаем, что там будет внутри. Поэтому для изготовления компилятора нам нужно тащить с собой весь интерпретатор. Или юзать ЯП без eval. Или как в sed/C(ВНЕЗАПНО man system(3)) использовать левый /bin/sh.
ну не тупи: «входные данные» это то, что внутри eval'а.
Нет. Еще раз - входных данных нету.
не. Ты точно идиот.
Еще раз - последовательность машинных команд бесконечна. Не потенциально и актуально. То есть кода нет.
что за команды ты там нафантазировал из ниоткуда?
Прои чем тут код обрабатывающий евал? После компиляции в программе не может быть вызовов евала, иначе компиляция не закончена.
с какого перепугу не может? Вот тебе твой eval актуально бесконечный: L: CALL L (IRL падает при переполнении стека). Этот eval выполняет код, в котором написано «выполнить eval который...»... Ну ты понял.
я сам такую хрень тыщу лет не писал. Обычно лучше использовать стек в куче с push/pop, но на ЛОРе мне лениво было делать нормальную реализацию стека, а списки с итераторами из STL мне не нравятся.
В стандарте есть std::stack с push/top/pop и автоматической памятью в куче, а если статично, то можно обвернуть std::array операциями и повесить в static:
Тут zero-cost — ассемблер на выходе всё равно такой же.
всё равно за такое убивают. И дело совсем не в ассемблере.
PS: мой компилятор сказал на твой говнокод:
In file included from /usr/include/c++/4.8.2/array:35:0,
from ev_qm.cpp:4:
/usr/include/c++/4.8.2/bits/c++0x_warning.h:32:2: ошибка: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support for the \
^
ev_qm.cpp:6:27: фатальная ошибка: boost/range.hpp: Нет такого файла или каталога
#include <boost/range.hpp>
^
компиляция прервана.
У меня тоже 4.8.2, ты не знаешь как собирать C++11 код?
всё равно за такое убивают. И дело совсем не в ассемблере.
А что не так? В лучших традициях PHP же — ДЛЯ (for) каждого ТЕРМА (term) из ДИАПАЗОНА (range) с НАЧАЛА (begin) ТЕРМОВ (terms) до КОНЦА (end) ТЕРМОВ (terms) НЕ СЧИТАЯ (- 1) последнего '\0'. И никаких тебе while(*tp), switch(*tp++), tp[-1], *sp, *sp++, sp[-1], sp[-2] и --sp.
Выполнение в образе вообще и eval в частности будут делать всё что угодно (eval будет определённым образом интерпретировать код который делает всё что угодно в рамках образа, в т.ч. зовёт компилятор, опять eval и т.п.). Но это нормально. save-lisp-and-die будет делать вполне конкретную вещь. compile во время раскрытия макросов будет делать всё что угодно, но это типа местная особенность — писать базовый лисп в макросах лиспом как угодно, если это пропустить, то дальше компиляция базового лиспа вполне обычна.
P.S. sh (в т.ч. exec*), hibernate и make (пропустить — cc) :)
Ну а как в целом описать процесс получения бинаря? Компиляция макросов и «базового» лиспа (и что-то мне подсказывает, что понятие неформализовано)? И дальнейшее обращение к интерпретатору (и, возможно компилятору) в образе.
Но, например, можно же (наверное долго и вряд ли кто-то делает) добавить к целям в исходниках pypy свой код и получить бинарь. По-моему довольно похоже («базовый лисп» <-> RPython). Но это же не делает из pypy _компилятор_ питона, почему же sbcl упорно называют компилятором. В любом случае, выхлоп «компилятора» не отпускается в свободное плавание, а обрабатывает вход под чутким контролем образа.