LINUX.ORG.RU

Homoiconic C

 homoiconicity,


3

2

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

Это ж кайф. Выражения типа regexp(«^[a-z][a-z0-9]») или format(«%s - %s (%d)», bla1, bla2, i) можно будет автоматически обрабатывать макропроцессором и отправлять компилятору оптимизированный вариант. Это значит, регулярка, например, будет скопилирована в конечный автомат при компиляции программы, а не при выполнении.

Вот эта вот странная задачка, на которой dr_jumba проверял лаконичность языков, записывалась бы как-то вот так:

sample_function := fn(a(iterable(T))) to(T) {
    a select(match(regexp(/^J[a-z]+/))) each_chunk(3) map(format_with("~1 and ~2 follow ~3")) join("\n")
}

Дискас.

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

Вы не поверите, но выражения типа F(known) где F - реализованная чистая функция, ещё лет д-цать назад расчитывались на макро АССЕМБЛЕРЕ ЕС ЭВМ.

поверю

(хотя интересно — это делалось интерпретатором, или функция компилировалась и запускалась?)

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

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

я так предполагаю, что методика вытаскивания AST — это подсунуть exec-y правильный mapping object

Да.

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

Не позволяет конечно. Если хочется достать ast полностью, то есть готовый модуль ast, он как раз такое делает. Но этого не хочется, если я хочу сгенерировать if, я использую свою библиотечную ф-ю If, которая чего то там сгенерит. А обычный if работает внутри exec-а и позволяет выбирать те или иные участки генерации. Т.е. получается что для написания макросов юзается вся питонячья моща, это не #define;-)

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

хотя интересно — это делалось интерпретатором, или функция компилировалась и запускалась?

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

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

значит ты не вводишь новый синтаксис, не ребайндишь переменные, не колбасишь ast... тогда что? делаешь partial evaluation?

Не позволяет конечно.

не факт что «конечно»

питон, мягко говоря, не блещет, но глядя на exec я начал подозревать, что у кого-то там у них хватило мозгов разрешить перегрузку if и остальных конструкций

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

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

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

Переменные ребайндю. AST предпочитаю колбасить при построении, но это не догма - можно работать и с готовым, просто при построении мне удобней. За partial evaluation ИМНО бегать глупо, компайлер его лучше меня сделает (насколько я понимаю).

питон, мягко говоря, не блещет, но глядя на exec я начал подозревать, что у кого-то там у них хватило мозгов разрешить перегрузку if и остальных конструкций

Как?

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

ЗЫ: одна из причин, почему Фортран долгое время в хвост и в гриву уделывал по производительности всякие там сишечки для числодробильни была в том, что у него есть встроенная в язык поддержка комплексных чисел.

Рыдал. Не говоря о том, что в числодробилках использование комплексных чисел скорее исключение, чем правило, в каком это лохматом году фортран уделывал С по производительности?

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

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

Например. Конкретно в LW мозг от такого не взрывался.

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

ACL2 vs. agda или coq

Я с ACL2 ничего не пробовал делать, так что хз.

Вот например — http://www.cs.utexas.edu/users/moore/publications/how-to-prove-thms/main.pdf, как раз там consы под структуры данных. Допустим, первый пример про то что данная copy для деревьев суть id для них. На агде это будет

module TreeCopy where

open import Level
open import Function
open import Relation.Binary.PropositionalEquality

data Tree (A : Set) : Set where
  [_] : A → Tree A
  _,_ : Tree A → Tree A → Tree A

copy : ∀ {A} → Tree A → Tree A
copy [ x ] = [ x ]
copy (x , y) = copy x , copy y

IsIdentity : ∀ {A} → (A → A) → Set
IsIdentity f = ∀ x → f x ≡ x

copy-is-identity : ∀ {A} → IsIdentity (copy {A})
copy-is-identity [ _ ] = refl
copy-is-identity (x , y) = cong₂ _,_ (copy-is-identity x) (copy-is-identity y)

postulate
  extensional : Extensionality zero zero

IsIdentityEx : ∀ {A} → (A → A) → Set
IsIdentityEx f = f ≡ id

copy-is-identity-ex : ∀ {A} → IsIdentityEx (copy {A})
copy-is-identity-ex = extensional copy-is-identity

то есть ни о чём.

Лично мне Agda/Coq интересны и сами по себе и даже в масштабе общей картины разных ЯП, ACL2 не вижу смысла смотреть.

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

Именно функциональный? Мне такой не известен. Теоретически, BitC должен был это уметь, но умер слишком рано.

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

(bad) не нужен, вообще этой ветки выполнения быть не должно

Почему не должно? С ней ведь все в порядке.

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

До фекспров дошли, еще чуть-чуть - и придумаете полноценный лисп.

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

питон, мягко говоря, не блещет, но глядя на exec я начал подозревать, что у кого-то там у них хватило мозгов разрешить перегрузку if и остальных конструкций

Как?

как в хаскеле

на слишком краткий вопрос — слишком краткий ответ :-)

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

Не-не, давайте поподробней. Я конечно расширял синтаксис питона, скажем скобочки свои вводил навроде [% %], {% %} и тд (для сложных алгебраических выражений), но код перед exec-ом просто преобразовывался и такие вещи заменлись на что то питоносъедобное. Но как можно перегрузить if и т.д. не расширяя синтаксис и не парся код руками? Я кроме как модуля ast ничего придумать не могу...

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

Но как можно перегрузить if и т.д. не расширяя синтаксис и не парся код руками?

Как в лиспах, например.

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

В говнолиспегах синтаксиса нет, парсить нечего. А в любом человечном языке парсить придется. Нунах. Расширять язык - западло.

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

В лиспах синтаксиса нет, парсить нечего. А в любом другом языке парсить придется. Нунах. Расширять не лисп - западло.

// fix от говна и ПГМа

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

Почему не должно?

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

С ней ведь все в порядке.

Она в исключительную ситуацию control flow приводит. Программа выполняется, в одном случае получается полезный результат, в другом — еггог, и почему я не могу хотеть обеспечить отсутствие его (то есть всей этой ветки выполнения) до запуска?

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

не расширяя синтаксис и не парся код руками?

В том же haskell AST можно получить, ничего руками не парся, с помощью квазицитирования. А уж перегрузить что нужно — ручками модифицируя AST.

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

P. S. Я уже представляю, какой разрыв шаблона случится у человека, читающего код с перегруженным if.

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

В том же haskell AST можно получить, ничего руками не парся, с помощью квазицитирования. А уж перегрузить что нужно — ручками модифицируя AST.

В квазицитатах не может быть квазицитат, так что не работает.

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

Ну и перегружать что-то парся и трансформируя АСТ - это уебищно. Нормально люди просто берут и переопределяют идентификатор.

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

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

У нас ничего не смешивалось и не ломалось. Смешивалось бы если бы бинд выполнился. А так тебе выдало ошибку - в точности как в статике.

Она в исключительную ситуацию control flow приводит.

Так же как и в статике.

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

и почему я не могу хотеть обеспечить отсутствие его (то есть всей этой ветки выполнения) до запуска?

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

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

Ну это в хачкеле для перегрузки все в квазицитаты надо засовывать. В полноценных ЯП и без этого обходятся.

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

Только для перегрузки конструкций языка. Нет ни одного полноценного языка, где можно было бы без этого обойтись.

Но если мы уже сделали свой особый хаскель, зачем внутри этого особого хаскеля делать ещё один особый язык?

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

я не говорил, что ТЫ можешь перегрузить if — я говорил о том, что у меня возникло подозрение, что у гвидо и К хватило мозгов придумать перегрузку if

но если ты не знаешь способа перегрузить — то скорее всего его и нет

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

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

if — уже 2 года (ну если быть совсем точным, то не в хаскеле, а в ghc-хаскеле)

http://hackage.haskell.org/trac/ghc/ticket/836

с остальными афайк все не так гладко

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

А... да, я когда читал доки, встречал там специфические описания ситнтаксиса и у меня было тоже ощущуение что ребята сделали хитрую фичу позволяющую расширять/патчить язык. Нефига, это не более чем способ описания;-(

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

Только для перегрузки конструкций языка. Нет ни одного полноценного языка, где можно было бы без этого обойтись

Как нет? Есть.

(define-syntax (if stx) yoba ...) ; перегружаем if

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

Есть «маленькая» разница — до запуска программы или после.

Конечно, нету. Разница есть в конкретном времени запуска. Важно, через какое время после написания кода будет обнаружена ошибка, а будет ли при этом запущена программа - никого не волнует.

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

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

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

Ну и где тут полноценный язык?

а чем 'это' не полноценный язык?

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

Ну и где тут полноценный язык?

Там и есть.

Как в голом AST это сделать и так ясно.

При чем тут голый АСТ, я не понял? Ну пусть будет так: defsyntax if(stx: Expr){yoba ...};

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

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

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

Ололо, лошара, квазицитирование - это просто синтаксический сахар над cons и quote. Соответственно, как раз квазицитированием можно сделать все, а вот гигиена твоя чмошная ограничена и убога.

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

жалкое квазицитирование.

Квазицитирование нужно для преобразования кода на произвольном языке в AST. С AST средствами языка можно творить что угодно, и потом это что угодно сплайсить. Или, например, делать pretty-print в какой-нибудь другой язык (в какой-нибудь C или CUDA).

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

Ну вот в одном случае вероятность найти до запуска (сразу по проверкам во время AOT) _все_ ошибки из определённых классов ошибок == 1 и == 0 для всех остальных классов ошибок. В другом — всегда == 0 (исключая разве что вещи которые тупо лексемы разобрать и AST построить не дают) до запуска и <= 1 для всех классов ошибок для любых промежутков времён после запуска (кто знает когда оно туда докатится и вывалится с исключением).

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

Твой пример на racket просто не «звучит» — задача в том, чтобы сделать язык-теорию в котором все программы имеют интерпретацию в модели [выполнения] в которой слои выполнения не смешиваются и исключительных ситуаций связанных с этим смешиванием не возникает, ты пишешь код и есть программы у которых нет правильной смысловой интерпретации в такой модели — исключения возникают, слои не смешиваются, но и поток выполнения рвётся. Он звучит только если ты хочешь падать в рантайме (тогда нужно спросить — как продолжать выполнение?) при каждой попытке смешать уровни — пожалуйста, но это не соответствует условию задачи.

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

Это проблемы хачикиля, а не квазицитат.

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