LINUX.ORG.RU

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

и приведением рекурсии к циклу (которое невозможно).

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

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

причём показал почему-то цикл, а не рекурсию. Ты ничего не перепутал?

Я показал гото, то есть хвостовую рекурсию. Циклы там постольку поскольку (можно было вместо них сделать другие гото, то есть рекурсию).

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

И слова «к хвостовому виду (CPO transformation)». Это ты их придумал. Я говорил «в цикл», но про CPO — твоя фантазия.

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

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

возможно, хотя и требует явного выделения памяти

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

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

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

Чему равно количество яблок, которые могут вырасти из одного семечка?

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

ну сделай в компиляторе HLT, что-бы смотрел также.

Тогда это сломает компилятор, так как семантика перестанет сохраняться. Он _должен_ смотреть иначе.

код чуток подправить, что-бы как в [dafaq], не останавливался

Код gcc поправить? Перестанет быть компилятором, говорю же.

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

дальше компиллил

Это win ящитаю.

чуток

Специалисты по коду gcc в треде.

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

а ты предлагаешь чтобы gcc не останавливался.

Я несколько утратил нить вашей беседы. Емулек предлагает, чтобы на виснущих программах компилятор тоже вис? А как компилятор должен отличить виснущую программу от невиснущей? Или пусть виснет на всех - нахуя вообще нам надо канпелировать чего-то там? :trollface:

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

-- Компилятор можно зациклить.

-- gcc можно?

-- Код чуток подправить, чтобы как в интерпретаторах, не останавливался, а дальше компилировал.

«как в интерпретаторах» «дальше компилировал» особо доставляет.

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

Только грим чуток подправить.

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

И последнее яблоко раздора, господа!

Как какому классу, в свете этого топика, отнести язык Forth?!

Думаю, что этот вопрос всех примирит :)

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

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

Тут вики глаголит, что построением AST занимаются только Перл и Руби перед выполнением... А все остальные транслируют в оптимизированный байт-код и выполняют.

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

Различных людей со Scheme головного мозга,создавших всякие там Racket'ы, мы рассматривать не будем.

Уже и так, по-моему, заговорились.

Слава Богу, что без баттхерта :)

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

Форт это среда со всем вместе.

http://www.wulfden.org/downloads/Forth_Resources/LB__StartingForth.pdf

Compile

to generate a dictionary entry in computer memory from source text (the written­out 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 (pre­defined) 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.

Например

http://github.com/AlexandreAbreu/jonesforth/blob/master/jonesforth.S

http://github.com/AlexandreAbreu/jonesforth/blob/master/jonesforth.f

(IR или машкод или «почти» машкод)

Какой-нибудь SBCL — тоже подобная среда, если в общем.

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

Тут вики глаголит, что построением AST занимаются только Перл и Руби перед выполнением...

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

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

Ну примерно так, да. VM работает на CPU, выполняет свои байткод-программы (полученные заранее компиляцией), если JIT компилирует (во время выполнения) их в машкод, то получается смешанное выполнение CPU -> VM -> байткод, CPU -> машкод от JIT.

Различных людей со Scheme головного мозга,создавших всякие там Racket'ы, мы рассматривать не будем.

Так они чем-то принципиально отличаются хоть от всего остального?

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

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

Ладно там метапрограммирование с ним то понятно.

Но здесь это ведь создает дополнительные накладные расходы на выполнение.

С какого горя, спрашивается?

Для таких вот ветвистых тредов, как этот?

то получается смешанное выполнение CPU -> VM -> байткод, CPU -> машкод от JIT.

Тут действительно машкода в его чистом виде нет, ибо машкод это ВМ, которая крутится как белка в колесе, выполняясь на ЦП, очевидно.

С этим я полностью согласен.

Именно на этой оптимистической ноте и хотелось бы завершить топик.

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

Я показал гото, то есть хвостовую рекурсию. Циклы там постольку поскольку (можно было вместо них сделать другие гото, то есть рекурсию).

тогда покажи нормальный пример, а не это говно.

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

Может, ты и Суслика не видел? и корень пятой степени из пи на е? А они есть.

в твоих фантазиях.

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

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

ты забыл спросить, сколько будет поделить на ноль.

Я отвечу на все твои вопросы, но не здесь.

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

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

ну. и?

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

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

Так это в любом языке с eval и JIT так будет. На C/C++ можно написать такой же код (то есть тупо — в цикле забивать всё время разный машкод в буфер, кастовать его к типу функции и вызывать на каждой итерации). Почему новый код генерится каждый раз — потому что попросили, вот он и генерится :)

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

А как компилятор должен отличить виснущую программу от невиснущей?

ну если quasimoto захерачил HLT, то программа должна зависнуть, и пофиг, компилятор/интерпретатор. Во имя вселенской эквивалентности.

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

H[A]LT

зависнуть

Англо-русский словарь тебе в руки.

пофиг, компилятор/интерпретатор

Компилятор не умеет виснуть, такие дела.

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

КПД такого компилятора ровно ноль.

ну и что? Я разве где-то говорил про КПД?

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

Англо-русский словарь тебе в руки.

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

Компилятор не умеет виснуть, такие дела.

словарь тебе в руки: у слова halt нет значения «зависнуть». Это скорее «hang».

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

Хм, а я опять приметил маленькое жульничество :)

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

Требую сатисфакции в виде ассемблерных ( ;) ) примеров кода, где именно он изменяется, а не данные (аргументы), которые он обрабатывает!

Иначе признавайте, что выкладки анонима, по крайней мере неполны :)

А то и вовсе поражение последнего в данном вопросе.

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

HLT относительно того языка это такая же штука как return statement из C, который return [<expr>]; — нам в компиляторе не «останавливаться» или «возвращать» надо, нам транслировать нужно и продолжать. А при выполнении уже останавливаться/возвращать.

Я разве где-то говорил про КПД?

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

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

Опкодам тоже не проблема меняться.

Требую сатисфакции в виде ассемблерных ( ;) ) примеров кода

Ну

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

Вперёд :)

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

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

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

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

С какого горя, спрашивается?

Просто код так написан. Если написать без евала - ничего генериться не будет. А евал дефайн-формы это по сути команда вм «создать код для указанной ф-и». Что ей сказали, то она и делает :)

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

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

тогда покажи нормальный пример

for (...){
    ...
    label 1;
    ...
    if (...) goto 2;
    ...
}

for (...){
    ...
    label 2;
    ...
    if (...) goto 1;
    ...
}

->

label start1:
    ...
    label 1;
    ...
    if (...) goto 2;
    label end1:
    ...
    if (...) goto start1

label start2:
    ...
    label 2;
    ...
    if (...) goto 1;
    label end2:
    ...
    if (...) goto start2;

->

(define (label-start1)
  ...)

(define (label1)
  ...
  (if (...) (label2) (label-end1)))

(define (label-end1)
  ...
  (if (...) (label-start1) (label-start2)))

(define (label-start2)
  ...)

(define (label2)
  ...
  (if (...) (label1) (label-end2)))

(define (label-end2)
  ...
  (if (...) (start2) (void)))

вот тебе на рекурсии тот же код что и с гото.

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

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

Так по факту меняется вся машинная комманда.

> (for ([i (in-range 2 10])
    (eval `(begin (define (f x) (,(if (even? i) 'unsafe-fx+ 'unsafe-fx*) x ,i)) (f 0)))
    (decompile f #:size 46))

00000000  488943F8          mov [rbx-0x8],rax
00000004  4883C3F8          add rbx,byte -0x8
00000008  488B4308          mov rax,[rbx+0x8]
0000000C  4883C004          add rax,byte +0x4
00000010  4C8B75C8          mov r14,[rbp-0x38]
00000014  4883C428          add rsp,byte +0x28
00000018  5F                pop rdi
00000019  5E                pop rsi
0000001A  5B                pop rbx
0000001B  5D                pop rbp
0000001C  C3                ret

00000000  488943F8          mov [rbx-0x8],rax
00000004  4883C3F8          add rbx,byte -0x8
00000008  488B4308          mov rax,[rbx+0x8]
0000000C  BA06000000        mov edx,0x6
00000011  4889C6            mov rsi,rax
00000014  48D1FE            sar rsi,1
00000017  480FAFF2          imul rsi,rdx
0000001B  4889F0            mov rax,rsi
0000001E  80C801            or al,0x1
00000021  4C8B75C8          mov r14,[rbp-0x38]
00000025  4883C428          add rsp,byte +0x28
00000029  5F                pop rdi
0000002A  5E                pop rsi
0000002B  5B                pop rbx
0000002C  5D                pop rbp
0000002D  C3                ret

достаточно разный код? :)

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

Да, в системе отсчета «ракеты» (или как ее там) действительно генерится новый двоичный код.

Это я проморгал...

Убедили :)

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

Это код. Многоточия может заполнить чем угодно. Важен тут CFG, а не то, что конкретное делается.

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

Да, в системе отсчета «ракеты» (или как ее там) действительно генерится новый двоичный код.

Не в ракете, а в _любом_ языке с евалом, который джитится/компилируется. Лиспы, питоны, пехепе, джаваскрипт, руби и так далее.

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

Это я так написал из-за интуитивного желания все-таки свернуть код в цикл ;)

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

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

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

Поясните тупому, что делает данный код.

Как я понимаю там в сначала идет сложение

четного числа, потом умножение четного же (в диапазоне от 2 до 10), только не понял самого на себя или 4*6 (не особо вникал)?!

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

Согласен с Вами :)

Еще раз спасибо за беседу, было интересно.

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

Поясните тупому, что делает данный код.

Если число четное, то мы получаем функцию: (define (f x) (+ x const)), если нечетное: (define (f x) (* x const)). То есть вычисляется выражение (if (even? i) '+ '*) для данного i и подставляется его результат (который будет '+ для четного числа и '* для нечетного) в код, который потом уходит на компиляцию. const на каждом шаге своя, понятно. итерации начиная с 2, потому что для случаев 0 и 1 эта ф-я вообще ничего складывать и умножать не будет - компилятор оптимизирует и возвращает сразу ответ (0 или х).

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

ЗЫ: unsafe-fx там добавляется, чтобы код итоговый был короче, в обычных +/* много лишнего (проверки аргументов, диспатчинг по типу и т.п.), в unsafe-версиях этих лишних вещей нет.

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

То есть число складывается или умножается само на себя?

Складывается либо умножается на аргумент функции.

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

Если число четное, то мы получаем функцию: (define (f x) (+ x const)), если нечетное: (define (f x) (* x const)). То есть вычисляется выражение (if (even? i) '+ '*) для данного i и подставляется его результат (который будет '+ для четного числа и '* для нечетного) в код, который потом уходит на компиляцию. const на каждом шаге своя, понятно. итерации начиная с 2, потому что для случаев 0 и 1 эта ф-я вообще ничего складывать и умножать не будет - компилятор оптимизирует и возвращает сразу ответ (0 или х).

ладно.

Принято.

На кой ляд это надо на практике?

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

В общем то я понял.

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

В некотором роде это схоже с концепцией шаблонного метапрограммирования в крестах (?).

Принято. Убедили.

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

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

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

Вот тупо интерпретатор сложения, тупой исполнитель. а потом бац — и в какие-то Z, S(a) сконпелировал. <LOL>откуда он знает???</LOL>

И вот что мне интересно: если как тут говорят, интерпретатор — это тупой исполнитель (а не транслятор), конпелятор — тупой транслятор (а не умный исполнитель каких-нибудь C++ шаблонов, например), то

В какой же именно момент здесь появляется транслятор?
ткните пальцем, а.

А то неудобно как-то: был исполнитель тупой, ещё тупее, и никакого транслятора не было. ob ovus.

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

в какой именно момент какой-нибудь там метациклический интерпретатор становится «транслятором»? так чтобы вот раньше не было, и бац — появилосЪ.

Здаёццо мне, что причина это связь здесь где-то между языком и метаязыком.

А то чего-то недоговаривают:

Интерпретатор чего именно — не транслятор, а тупо исполнитель? тупого языка, где метаязыком ещё и не валялосЪ.

Интерпретатор метаязыка — это кто? исполнитель метаязыка? это как ? трансляцией метаязыка в язык?

А можно ли в принципе хоть как-нибудь по другому, «непосредственным тупо исполнением метаязыка» ??? если у нас turtles all the way down?

Затем, прогонка интерпретатора метаязыка. и построение остаточной программы. то есть суперкомпиляция — и результат оной, компилятор. компилятор чего именно? языка, а не метаязыка (хотя в случае шаблонов С++ вполне себе метаязык)

и уже сразу — бац, такой маленький, а уже тrанслятоr.

*вопрос*, в какой именно момент развития метаязыка у нас появляется трансляторъ ?

а то у нас эдак и 0,1,2,3.. тоже ординалы, чай не омегой или епсилон нулевым одними (начнёшь поутру так подсчитывать — и к вечеру не закончишь), да и язык HQ9+, и «единичное отображение» тоже метаязыки.

только маленькiя ишшо.

болели много, каши кушали мало (а макарон — много (или), пыщь), вот и irreducible графы не выводили символьно в другую сторону (на то они и irreducible.. а вот зачем irreducible, т.е., нафига?? нафига зацикливать аксиому выбора?).

ну тупыыыыееее.... обратимых (инвертируемых) вычислений на них нет!!!

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

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

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

почему енто так, ведь процесс заправки одинаковый??? когда ем, на входе — всё такое вкусное.. а вот на выходе...

подходы разные, а результат — на выходе — одинаков.

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

И кстати перечитай учебник, там много чего написано, но вот того, что эти ℚ можно сопоставить с RL — не написано.

читай учебник по музыке. пифагоров строй и хорошо темперированный строй.

философию музыки. теорию музыки

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

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

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

а там и до философии не так уж далеко

а ты — не написано, не написано. выкинь свой учебник и возьми новый

IRL нет у нас «идеально острого ножа» и «бесконечно делимых яблок». Потому поделить яблоко можно только на конечное число частей.

зато есть «бесконечно умножаемые яблоки». а умножать, умножать-то можно? а деление — обратная операция.

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

а теперь выполняем обратную операцию — сколько семачек нужно для получения этого заданного количества яблок ???

теперь делим яблоко, достаём «конечное число семачек». и математический чайник.

Правда с такой математикой яблоки делить не очень хорошо, ибо 2*2=1, а отсюда следует, что 1/2=2. Т.е. если у нас всего 3 яблока, и мы хотим два яблока оставить себе, а половину из того, что останется отдать, то нам нужно отдать 2 яблока из одного... Причём из этого одного яблока мы два яблока отдадим, и ещё два останется. Бред? Да.

не бред. «отдаём 2 яблока из одного» := одно целиком, другое семачками на вырост. через яблоню. и ещё на посев останется.

ну или это четырёхмерные space eggs шары такие, которые один в один вкладываются. Банаха-Тарского. пыщь!

ты вообще оставаясь в 3D не можешь наверняка утверждать — это 3D у тебя яблоки или просто 3D поверхности 4D сферического яблока в вакууме.

если уж на то пошло, то у яблони размерность фрактала. почему у яблока должно быть по-другому? яблоко — это особенность на этом фрактале. оно тоже фрактал.

один фрактал содержит другой, ещё и эволюционирует во времени.

а вы: «энергия конечна, конечна». в жизне энтропия-то почему-то не убывает?

система «жизня» открыта, незамкнута. одно дело если про размерность фрактала, другое про длину его периметра.

пруфлинк простой — жизнь продолжается, пока всё идёт нормально =))

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