И слова «к хвостовому виду (CPO transformation)». Это ты их придумал. Я говорил «в цикл», но про CPO — твоя фантазия.
Ну да, говорил-то ты про цикл, но имел ввиду именно CPO, потому что перепутал. К CPO любая рекурсия, действительно, приводится, к циклам - нет, не приводится.
Нет, ты сейчас говоришь про CPO (которое возможно, но при явном выделении памяти), а приведение к циклу - невозможно в случае irreducible графа. Сколько уже можно?
Я несколько утратил нить вашей беседы. Емулек предлагает, чтобы на виснущих программах компилятор тоже вис? А как компилятор должен отличить виснущую программу от невиснущей? Или пусть виснет на всех - нахуя вообще нам надо канпелировать чего-то там? :trollface:
Тут вики глаголит, что построением AST занимаются только Перл и Руби перед выполнением...
А все остальные транслируют в оптимизированный байт-код и выполняют.
Вся соль в том, насколько я понимаю, что машкода не существуют с точки зрения программы внутри ВМ, есть только байт-код, который и выполняется на ЦП через ВМ, но уже как машкод, с точки зрения железа.
Различных людей со Scheme головного мозга,создавших всякие там Racket'ы, мы рассматривать не будем.
to generate a dictionary entry in computer memory from source text (the writtenout form of a definition). Distinct from «execute.»
Execute
to perform. Specifically, to execute a word is to perform the operations specified in the compiled definition of the word.
Interpret
(when referring to Forth's text interpreter) to read the input stream, then to find each word in the dictionary or, failing that, to convert it to a number.
Dictionary
in Forth, a list of words and definitions including both «system» definitions (predefined) and «user» definitions (which you invent). A dictionary resides in computer memory in compiled form
When you define a new word, Forth translates your definition into dictionary form and writes the entry in the dictionary. This process is called «compiling.»
The text interpreter scans the input stream, looking for strings of characters separated by spaces. When a string is found, it is looked up in the dictionary. If the word is in the dictionary, it is pointed out to a word called EXECUTE. EXECUTE executes the definition (in this case an asterisk is printed). Finally, the interpreter says everything's «ok.»
The text interpreter finds the colon in the input stream, and points it out to EXECUTE. The compiler translates the definition into dictionary form and writes it in the dictionary. When the compiler gets to the semicolon, he stops, and execution returns to the text interpreter, who gives the message ok.
Тут вики глаголит, что построением AST занимаются только Перл и Руби перед выполнением...
Не построением, а выполнением посредством обхода AST (вместо генерации и интерпретации байткода — в таком случае AST строить всё равно типично перед тем как начать трансляцию в байткод).
машкода не существуют с точки зрения программы внутри ВМ, есть только байт-код, который и выполняется на ЦП через ВМ, но уже как машкод, с точки зрения железа.
Ну примерно так, да. VM работает на CPU, выполняет свои байткод-программы (полученные заранее компиляцией), если JIT компилирует (во время выполнения) их в машкод, то получается смешанное выполнение CPU -> VM -> байткод, CPU -> машкод от JIT.
Различных людей со Scheme головного мозга,создавших всякие там Racket'ы, мы рассматривать не будем.
Так они чем-то принципиально отличаются хоть от всего остального?
Отличаются тем, что непонятно с какой целью создавался язык, где при определенных условиях, на одно и тоже действие динамически генериться разный код? Об этом уже неоднократно упоминал анонимус
Ладно там метапрограммирование с ним то понятно.
Но здесь это ведь создает дополнительные накладные расходы на выполнение.
С какого горя, спрашивается?
Для таких вот ветвистых тредов, как этот?
то получается смешанное выполнение CPU -> VM -> байткод, CPU -> машкод от JIT.
Тут действительно машкода в его чистом виде нет, ибо машкод это ВМ, которая крутится как белка в колесе, выполняясь на ЦП, очевидно.
С этим я полностью согласен.
Именно на этой оптимистической ноте и хотелось бы завершить топик.
Конкретно про яблоки — легко. Где существуют яблоки, когда они ещё в семечках? Сколько яблок вырастет из одного семечка (включая яблоню) ??? Чему равно количество яблок, которые могут вырасти из одного семечка?
ты забыл спросить, сколько будет поделить на ноль.
на одно и тоже действие динамически генериться разный код?
Так это в любом языке с eval и JIT так будет. На C/C++ можно написать такой же код (то есть тупо — в цикле забивать всё время разный машкод в буфер, кастовать его к типу функции и вызывать на каждой итерации). Почему новый код генерится каждый раз — потому что попросили, вот он и генерится :)
HLT относительно того языка это такая же штука как return statement из C, который return [<expr>]; — нам в компиляторе не «останавливаться» или «возвращать» надо, нам транслировать нужно и продолжать. А при выполнении уже останавливаться/возвращать.
Я разве где-то говорил про КПД?
Он вообще не выполняет своей функции, если есть компилятор, то он не виснет, если он виснет то это уже не компилятор, или как минимум сломанный (то же при несохранении семантики).
Требую сатисфакции в виде ассемблерных ( ;) ) примеров кода
Ну
то есть тупо — в цикле забивать всё время разный машкод в буфер, кастовать его к типу функции и вызывать на каждой итерации
Вперёд :)
А так — трейсинг машинного кода REPL-а вообще одна большая каша из никак не упорядоченного кода — придумал функцию, написал, скомпилировал, выполнил и т.д., всё это в рамках одного выполнения одной и той же машины, при том что исходный код последней конечен и обозреваем («одно и тоже ``действие``» — «динамически генериться разный код»).
Отличаются тем, что непонятно с какой целью создавался язык, где при определенных условиях, на одно и тоже действие динамически генериться разный код?
Не отличаются. В любой языке с евалом и джитом будет точно так же генериться разный код.
С какого горя, спрашивается?
Просто код так написан. Если написать без евала - ничего генериться не будет. А евал дефайн-формы это по сути команда вм «создать код для указанной ф-и». Что ей сказали, то она и делает :)
На практике можно, например, в рантайме создавать код заточенный под конкретные входные данные, компилировать его и за счет этого получать профит в производительности.
четного числа, потом умножение четного же
(в диапазоне от 2 до 10), только
не понял самого на себя или 4*6 (не особо вникал)?!
Тут правда и действия разные. Так что с форматом машинной команды более показательный пример. Без различных фокусов действительно код там будет разный, т.к. там операнд часть машинной команды.
Если число четное, то мы получаем функцию: (define (f x) (+ x const)), если нечетное: (define (f x) (* x const)). То есть вычисляется выражение (if (even? i) '+ '*) для данного i и подставляется его результат (который будет '+ для четного числа и '* для нечетного) в код, который потом уходит на компиляцию. const на каждом шаге своя, понятно. итерации начиная с 2, потому что для случаев 0 и 1 эта ф-я вообще ничего складывать и умножать не будет - компилятор оптимизирует и возвращает сразу ответ (0 или х).
Потом эта функция применяется к нулю (чтобы ф-я заджитилась ее надо вызвать). Потом выводим ее код. И на следующую итерацию, где делаем новую ф-ю и так далее.
ЗЫ: unsafe-fx там добавляется, чтобы код итоговый был короче, в обычных +/* много лишнего (проверки аргументов, диспатчинг по типу и т.п.), в unsafe-версиях этих лишних вещей нет.
Если число четное, то мы получаем функцию: (define (f x) (+ x const)), если нечетное: (define (f x) (* x const)). То есть вычисляется выражение (if (even? i) '+ '*) для данного i и подставляется его результат (который будет '+ для четного числа и '* для нечетного) в код, который потом уходит на компиляцию. const на каждом шаге своя, понятно. итерации начиная с 2, потому что для случаев 0 и 1 эта ф-я вообще ничего складывать и умножать не будет - компилятор оптимизирует и возвращает сразу ответ (0 или х).
Нашу с эмульком стройную картину мира разрушил тот факт, что при вычислении некоторого выражения входные данные берутся из определенного диапазона потому и код разный.
То есть действительно они не могут быть однозначно заданы до вычисления выражения «на лету», в процессе выполнения.
В некотором роде это схоже с концепцией шаблонного метапрограммирования в крестах (?).
Вот тупо интерпретатор сложения, тупой исполнитель. а потом бац — и в какие-то Z, S(a) сконпелировал. <LOL>откуда он знает???</LOL>
И вот что мне интересно: если как тут говорят, интерпретатор — это тупой исполнитель (а не транслятор), конпелятор — тупой транслятор (а не умный исполнитель каких-нибудь C++ шаблонов, например), то
В какой же именно момент здесь появляется транслятор?
ткните пальцем, а.
А то неудобно как-то: был исполнитель тупой, ещё тупее, и никакого транслятора не было. ob ovus.
в какой именно момент какой-нибудь там
метациклический интерпретатор становится «транслятором»? так чтобы вот раньше не было, и бац — появилосЪ.
Здаёццо мне, что причина это связь здесь где-то между языком и метаязыком.
А то чего-то недоговаривают:
Интерпретатор чего именно — не транслятор, а тупо исполнитель? тупого языка, где метаязыком ещё и не валялосЪ.
Интерпретатор метаязыка — это кто? исполнитель метаязыка? это как ? трансляцией метаязыка в язык?
А можно ли в принципе хоть как-нибудь по другому, «непосредственным тупо исполнением метаязыка» ??? если у нас turtles all the way down?
Затем, прогонка интерпретатора метаязыка. и построение остаточной программы. то есть суперкомпиляция — и результат оной, компилятор. компилятор чего именно? языка, а не метаязыка (хотя в случае шаблонов С++ вполне себе метаязык)
и уже сразу — бац, такой маленький, а уже тrанслятоr.
*вопрос*, в какой именно момент развития метаязыка у нас появляется трансляторъ ?
а то у нас эдак и 0,1,2,3.. тоже ординалы, чай не омегой или епсилон нулевым одними (начнёшь поутру так подсчитывать — и к вечеру не закончишь), да и язык HQ9+, и «единичное отображение» тоже метаязыки.
только маленькiя ишшо.
болели много, каши кушали мало (а макарон — много (или), пыщь), вот и irreducible графы не выводили символьно в другую сторону (на то они и irreducible.. а вот зачем irreducible, т.е., нафига?? нафига зацикливать аксиому выбора?).
ну тупыыыыееее.... обратимых (инвертируемых) вычислений на них нет!!!
in the interpretation approach, a program written in a source language S is directly executed by an S-interpreter, which is a program written in an implementation language. 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. The translation itself is performed by a translator program written in an implementation language. A translator is also called a compiler, especially when it translates from a high-level language to a low-level one.
странно же, неоднозначно написано.
... :- ...
?- «program written in an implementation language»
=>
1)S-interpreter/interp approach
2)result executed by T-interpreter/translator program/compiler/transl. approach
заправив кашу маслом, мы получаем кашу, то есть, конпелятор.
а заправив говном — получаем говно.
почему енто так, ведь процесс заправки одинаковый??? когда ем, на входе — всё такое вкусное.. а вот на выходе...
подходы разные, а результат — на выходе — одинаков.
а ты — не написано, не написано. выкинь свой учебник и возьми новый
IRL нет у нас «идеально острого ножа» и «бесконечно делимых яблок». Потому поделить яблоко можно только на конечное число частей.
зато есть «бесконечно умножаемые яблоки».
а умножать, умножать-то можно? а деление — обратная операция.
берём семечко, умножаем. семачко прорастает, получаются яблоня. она даёт яблоки. из кототорых выковыриваем семачки.
а теперь выполняем обратную операцию — сколько семачек нужно для получения этого заданного количества яблок ???
теперь делим яблоко, достаём «конечное число семачек». и математический чайник.
Правда с такой математикой яблоки делить не очень хорошо, ибо 2*2=1, а отсюда следует, что 1/2=2. Т.е. если у нас всего 3 яблока, и мы хотим два яблока оставить себе, а половину из того, что останется отдать, то нам нужно отдать 2 яблока из одного... Причём из этого одного яблока мы два яблока отдадим, и ещё два останется. Бред? Да.
не бред. «отдаём 2 яблока из одного» := одно целиком, другое семачками на вырост. через яблоню. и ещё на посев останется.
ну или это четырёхмерные space eggs шары такие, которые один в один вкладываются. Банаха-Тарского. пыщь!
ты вообще оставаясь в 3D не можешь наверняка утверждать — это 3D у тебя яблоки или просто 3D поверхности 4D сферического яблока в вакууме.
если уж на то пошло, то у яблони размерность фрактала. почему у яблока должно быть по-другому? яблоко — это особенность на этом фрактале. оно тоже фрактал.
один фрактал содержит другой, ещё и эволюционирует во времени.
а вы: «энергия конечна, конечна». в жизне энтропия-то почему-то не убывает?
система «жизня» открыта, незамкнута. одно дело если про размерность фрактала, другое про длину его периметра.
пруфлинк простой — жизнь продолжается, пока всё идёт нормально =))