LINUX.ORG.RU

Emulek-style programming


2

1

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

Взгляд emulek на процесс заключается, насколько я понял, в следующем. Поскольку строки представлены для проца маш кодом, можно считать их скомпилированными прогами. Поэтому, можно взять компилятор, вызвать из него интерпретатор, исполнить этим интерпретатором код, понятный этому интерпретатору, и, вуаля, у нас скомпилированная прога, в виде строки выхлопа интерпретатора (представленая в машкоде).

Давайте оформим эту мысль вот так. Есть 2 ЯП l1 и l2. Есть транслятор с l1 в l2 — это компилятор, назовем его К, и есть транслятор с l1 в l1 — это интерпретатор — И.

Представим себе, что мы выполнили текст на языке l1 c помощью И

text(l1) --> И --> text(l1)
и с помощью K
text(l1) --> K --> text(l2)
Пока все вроде ок, все работает одинаково. А теперь представим себе такую ситуацию
(text(l1) --> И --> text(l1)) --> И --> text(l1)
Мы выполнили выходную строку текста как программу — подали ее вновь на вход транслятору. Иными словами мы выполнили сгенерированную в рантайме программу.

Может ли транслятор K сделать то же самое? Только с помощью костылей, типа макросов и препроцессоров. Но есть тонкий момент. Что если нам нужно сделать

((text(l1) --> И --> text(l1)) --> И --> text(l1)) --> И --> text(l1)
?

Тут у нас всплывает, ИМХО, суть того, что принято называть мощностью ЯП.

А Вы за Emulek-style или против?:)


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

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

Эм... Нет, не понял.

Да, в нормальном языке, переменная — это просто переменная а не динамическая/статическая/элитарная/специальная.

Это тут вообще причем?

Так что не так с переменными в моем примере?

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

Проще говоря, переписывает текст. Это и есть компиляция.

это трансляция. Компиляция - просто трансляция в язык машины, железной или виртуальной.

В случае компиляции никакая семантика не сохраняется.

да ладно. Уважаемый господин понимает слово «семантика»?

Есть лишь забота о том, чтобы выходной текст был корректной программой для target-исполнителя.

и семантически соответствовал входному, дадада.

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

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

Алгоритм тут это тотальный алгоритм, в смысле Кнута и т.п., http://en.wikipedia.org/wiki/Algorithm.

Проще говоря, переписывает текст. Это и есть компиляция.

http://en.wikipedia.org/wiki/Translator_(computing), компилятор это разговорный смысл для «высокий уровень» -> «низкий уровень», бывает ещё декомпилятор и т.п.

Какую семантику?

Чем отличается компилятор от интерпретатора? (комментарий), две последние ссылки.

Грубо говоря, если write(read() + read()) имеет вполне чёткую семантику, то и результат трансляции должен иметь её же — нельзя транслировать во что попало, и так для всех программ — иначе это не трансляция (произвольная функция между языками с известной семантикой это не трансляция).

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

Ты написал eval = id, так что я его выкидываю, остальное:

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

но никуда не транслируется

В вашем случае оно точно также транслируется в текст, который идет на вход read. Eval тут неявный, потому что не нужна обработка в зависимости от типа или сигнатуры. Если бы она понадобилась, пришлось бы писать eval, или захардкорить его в функцию, что сути не изменит. Отдельный eval необходим, только если мы хотим его вынести на уровень языка, который интерпретируем.

но никуда не транслируется

Она транслируется в текст и подается на вход интерпретатора. То, что текст не выводится на дисплей, не говорит о том, что его нет.

а не быть id.

id - это тоже функция, типа

(lambda(x) x)
Это когда мы с точки зрения ФП смотрим на нее как на статику, а по факту, никто не запрещает делать вычисление было: <the_expr>; стало <the_expr>, и эти 2 записи не есть одно и то же, это 2 разные записи с одинаковой формой.

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

высокий уровень» -> «низкий уровень»,

А я, кстати, абстрагировался от уровней. Я написал просто: из языка А в язык В. Для понимания процесса уровни не важны, и не важно зачем мы что-то переписываем.

нельзя транслировать во что попало

А кто запрещает? Можно оттранслировать в непонятную хрень, а потом для этой непонятной хрени написать исполнитель.

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

В вашем случае

Обе функции repl вообще не имеют отношения к интерпретации "(loop)", говорю же (либо напиши настоящий REPL — тогда можно будет обсудить).

в L-языке есть программа "(loop)" которая L-интерпретатором выполняется сколько угодно долго, но никуда не транслируется. Она _может_ каким-то транслятором переводится в программу на T-языке (которую может выполнять, не транслировать, T-интерпретатор).

Не понятно?

А кто запрещает? Можно оттранслировать в непонятную хрень, а потом для этой непонятной хрени написать исполнитель.

Ещё реприза:

произвольная функция между языками с известной семантикой это не трансляция

То есть если есть си и ассемблер, например, то трансляция предполагает сохранение семантики.

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

А я, кстати, абстрагировался от уровней. Я написал просто: из языка А в язык В. Для понимания процесса уровни не важны, и не важно зачем мы что-то переписываем.

вот тогда нефиг писать «компиляция». Трансляция, и все.

Можно оттранслировать в непонятную хрень, а потом для этой непонятной хрени написать исполнитель.

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

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

Так что не так с переменными

Все не так. В этом вашем языке куча их: defparameter, defun, defvar, set, setf... Цирк ушел, а клоуны остались. А в нормальном ЯП есть просто объявление, и больше ни хрена. А не задумывался зачем обычно вводятся сущности? Для преодоления недостатков дизайна, мне кэп тут подсказывает. Приколачивают гвоздями фичи, которых лишены вследствии усложнения. Этим все сказано.

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

произвольная функция между языками с известной семантикой это не трансляция

А функция, BTW, это и так не трансляция, это лишь ее описание.

Что касается репла, он нормален. Он достаточен для демонстрации идеи, а расширять его можно до бесконечности, это ничего не изменит принципиально.

сохранение семантики.

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

phill
() автор топика
Ответ на: комментарий от arkhnchul

сохраняется семантика входной программы, а не языка.

С этим я не спорю

phill
() автор топика
Ответ на: комментарий от arkhnchul

Но это опять же, частный случай трансляции — компиляция. Интерпретация под это правило не подходит.

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

Но это опять же, частный случай трансляции — компиляция.

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

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

Она транслируется в текст и подается на вход интерпретатора.

она не транслируется. Преобразование внутри одного языка - не трансляция.

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

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

Общий случай — трансляция. Компиляция и интерпретация — это частные случаи.

phill
() автор топика
Ответ на: комментарий от arkhnchul

Преобразование внутри одного языка - не трансляция.

Во первых — пруф

Во вторых, язык — это понятие зыбкое, каждая функция расширяет язык, и это уже «не тот язык» на каждой следующей строке он «другой».

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

Общий случай — трансляция.

кто бы спорил. Однакож, вспомним, с чего началось:

который за конечное время превращает элементы одного языка в элементы другого определённым образом

Проще говоря, переписывает текст. Это и есть компиляция.

«переписывает текст» - «это и есть» трансляция.

Компиляция и интерпретация — это частные случаи.

интерпретация - нет, она к трансляции отношения не имеет.

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

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

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

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

Во первых — пруф

пруф чего? Во всех определениях трансляции прямо говорится, что целевой язык не соответствует исходному.

каждая функция расширяет язык, и это уже «не тот язык»

большими буквами: НЕТ. Язык в нашем случае - набор не функций, а совокупность формальных правил, описывающих лексемы языка, синтаксис (=набор допустимых сочетаний лексем) и семантику (=смысловое значение синтаксически правильных наборов лексем). Строго говоря, функция - часть не языка, а реализации.

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

Все не так. В этом вашем языке куча их: defparameter, defun, defvar, set, setf... Цирк ушел, а клоуны остались. А в нормальном ЯП есть просто объявление, и больше ни хрена...

Лол, сколько бреда. Но как это все связано с eval?

korvin_ ★★★★★
()

Один дебил за счет другого пиарится.
Язабан обоих туловищей.

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

А потом мы написали исполнитель.

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

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

А что у теоретиков есть единое мнение на этот счет? Мне по-барабану, кто что и как называет. Программирование в заднице, все заточено на быдлокодинг индусни. Важна суть, слова не важны.

phill
() автор топика
Ответ на: комментарий от arkhnchul

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

phill
() автор топика
Ответ на: комментарий от arkhnchul

вообще-то да.

Оно и видно. Посмотри на ссылку в начале топика. Больше десяти страниц срача, и к единому мнению так и не пришли. Видимо эти теоретики настолько мутно высказали это свое мнение, что никто непонел, включая их же самих.

phill
() автор топика
Ответ на: комментарий от arkhnchul

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

Хорошо, а что насчет спецформ, макросов и тд? И что, тогда получается, что нативные функции языка не являются частью языка?

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

А функция, BTW, это и так не трансляция, это лишь ее описание.

Произвольная [реализуемая как частичный или тотальный алгоритм] функция между языками с известной семантикой это не трансляция [реализуемая как тотальный алгоритм].

Что касается репла, он нормален. Он достаточен для демонстрации идеи, а расширять его можно до бесконечности, это ничего не изменит принципиально.

Ты о чём вообще? Какой идеи? Я говорю, что "(loop)" _интерпретируется_ бесконечно долго (потому что такова его семантика) и никуда не транслируется (некуда), ты про какой-то REPL который даже не работает (если бы он работал, то он бы интерпретировал "(loop)" бесконечно долго).

У си и асма разные семантики, не так ли?

Предполагается общий денотат. «Интерпретация» может пониматься как построение L-машины, тогда можно ввести понятие «наблюдаемого поведения», общего для разных машин.

http://gallium.inria.fr/~xleroy/publi/compcert-CACM.pdf

http://compcert.inria.fr/doc/ (semantic preservation theorems)

http://adam.chlipala.net/cpdt/html/StackMachine.html (Translation Correctness)

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

если бы он работал, то он бы интерпретировал "(loop)" бесконечно долго

А он что этого разве не делает?

phill
() автор топика

ничего, что emulek тролль, лжец, и девственник?

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

Результат трансляции "(loop)" (на языке CL) который даёт интерпретатор (языка CL) при интерпретации этой программы — в студию!

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

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

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

Интересные задачки, с подковыркой. REPL жа он и сам является лупом. Что пишет сам репл, то и пишет loop, все просто. Результатом трансляции loop будет все что он написал за время своей работы, пока его не убили. Если исключить из REPL'а print, которая принимает результат трансляции, он будет транслировать в никуда. Можно направить в файл. Куда угодно, это не важно. Что делает eval? Она берет текст прочитанный со ввода, и перезаписывает его. «foo»-->eval-->«bar». А полностью это будет «foo»-->in-->read-->eval-->print-->out-->«bar» Если мы хотим зациклить процесс, мы можем сделать так, чтобы с out текст сразу перенаправлялся в in.

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

phill
() автор топика
Ответ на: комментарий от phill
* (defun repl () (loop (format t "start REP~%") (format t "~S~%" (eval (read))) (format t "end REP~%")))

REPL
* (repl)
start REP
(format t "1~%")
1
NIL
end REP
start REP
(labels ((rec () (rec))) (rec))
; non-termination

выполнением (rec) занимается не L из REPL, а E, на одном шаге L вычислитель E зацикливается при выполнении (rec) — просто молча висит пока не прибьют.

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

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

Считай, что я под «трансляция» всегда подразумеваю «компиляция» — интерпретатор компилирует loop во всё что он напишет за время своей работы, пока его не убили? nginx будет компилироваться во все результаты своей работы по мере своей работы? Серьёзно?

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

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

Тут как раз все просто. (if(= (read) «exit») (exit)) Это заложено в eval.

Сам по себе REPL — это цикл, который заставляет запускаться транслятор вновь и вновь. А каждый перезапуск обеспечивает перезапись того что поступило. Какие тут матаны могут быть я не пойму?

Считай, что я под «трансляция» всегда подразумеваю «компиляция»

Вот реальное отличие интерпретации от компиляции:

(define eval
   (lambda(expr)
      (cond
         ((atom? expr) (do_staff expr))
         ((list? expr) (cond (qouted? (car expr)) ....)))))
(repl); где внутри eval
(define eval
   (lambda(expr)
      (cond
         ((foo? expr) (101010100))
         ((bar? expr) (0010100101)) ....)))))
(repl); где внутри eval
чтобы читать весь файл много ума не надо, пишем цикл, он весь файл читает и пишет в другой на конвейре. То есть, компилятор — это вообще тот же самый интерпретатор, только он переписывает в другой ЯП, на этом все отличие и кончается. Дальше — детали.

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

А eval - это как раз та машина, которая осуществляет эту перезапись, задает ее правила.

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

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

ну опять. Бредогенератор становится транслятором в тот момент, в который ты говоришь: бредотекст будет состоять из такого-то множества бредолексем, бредолексемы могут объединяться исключительно в такие-то бредопоследовательности, синтаксически правильные бредопоследовательности бредолексем будут означать такие-то и такие-то действия со стороны будущего бредоисполнителя, результат работы над получившимся бредотекстом оного бредоисполнителя и общий ход его действий будет соответствовать результату работы и общему ходу дейтвий исполнителя исходного языка, которому скормили исходный текст. Так понятно?

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

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

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

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

(if(= (read) «exit») (exit))

Какие тут матаны могут быть я не пойму?

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

http://en.wikipedia.org/wiki/Rice's_theorem

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

REPL

Давай оставим его в покое.

Вот реальное отличие интерпретации от компиляции

Ну вот почти, идеализируем — одно это чистая функция f : Source -> Target реализуемая алгоритмом который должен работать за конечное время — всякой программе ставить в соответствие одну и ту же программу другого языка, то есть вкидываем текст, принимаем текст; а другое это полноценное выполнение Source без трансляции (компиляции) — с эффектами и т.п., вкидываем текст, получаем работу (и вовсе не обязательно текст и не обязательно за конечное время).

на этом все отличие и кончается

Отличие довольно большое — компилируешь ты что-то или запускаешь на выполнение.

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

Ага, только в реальности всё сложнее — исходники много чего открыты, можешь почитать (вместе с книжками, например).

То есть, компилятор — это вообще тот же самый интерпретатор, только он переписывает в другой ЯП

И так никто не говорит.

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

Хорошо, а что насчет спецформ, макросов и тд? И что, тогда получается, что нативные функции языка не являются частью языка?

ты под спецформами что имеешь в виду? И какие именно макросы - C, CL, еще что-то? Сишные макросы, например, частью именно C как языка емнип не являются, это фича реализации.

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

Не особо. Вы может не можете излагать свои мысли просто, я излагаю очень просто. Есть машина M, вот как она работает: text1-->M-->text2. Является ли text2 корректной программой для некой машины M2, существует ли эта машина, будет ли она существовать, вопрос второстепенный, он не имеет отношения к процессу трансляции. Мы, для простоты вообще можем предполагать, что всегда найдется машина MX, которая исполнит текст TX.

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

этот тред скушный. создай новый

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

Вы может не можете излагать свои мысли просто, я излагаю очень просто

и неправильно.

Является ли text2 корректной программой для некой машины M2, ... вопрос второстепенный, он не имеет отношения к процессу трансляции

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

Мы, для простоты вообще можем предполагать, что всегда найдется машина MX, которая исполнит текст TX.

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

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

/Halting_problem

Эта проблема тривиальна. Я бы кастрировал того урода, который парит мозги. Если у тебя затруднения с пониманием оной я объясню очень просто, на пальцах. Я что говорил что я решаю проблему останова? Поступит ли exit на вход или нет,никто не знает. Это проблема программиста, обеспечить остановку. Ты когда факториал считаешь, поди не забываешь терминальную ветку в функцию вставить?

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

Давай оставим девочкам это «выполнение» а? Выполнение это процесс трансляции и больше ничего.

только в реальности всё сложнее

В реальности вообще коррупция кругом и преступность, нам бы хот с моделью пока разобраться:)

И так никто не говорит.

Леммингопроблемы.

phill
() автор топика
Ответ на: комментарий от arkhnchul

Короче, вопрос в названии, японел.

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

Выполнение это процесс трансляции и больше ничего.

еще раз: НЕТ. Разупорись. Выполнение кода исполнителем к трансляции отношения не имеет вообще никакого.

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