LINUX.ORG.RU

lisp как препроцессор для C


0

0

Ура, вот и настал мой звёздный час. Наконец-то я надёжно заработаю посмертное попадание в ад, где буду, загорая на сковородке, обсуждать с лисперами-сатанистами дела давно минувших дней. Но приступим к делу. Предлагается создать open-source библиотеку, являющуюся лисповым синтаксисом для С.

Это не будет embedded lisp. Это не будет связка lisp-C по FFI или через IPC (хотя это возможно). Это не будет очередная виртуальная машина (хотя и это возможно). Это будет лисповая оболочка над С.

Будет иметься постоянно запущенная лисп-среда, своего рода "пчела-матка", которая будет генерировать C-код. С-код будет компилироваться обычным C-компилятором и потом исполняться отдельно.

Что мы возьмём от С? Всё. Результатом работы первой фазы компилятора будет обычный С-код.

Что мы возьмём от лиспа? Синтаксис. Синтаксис лиспа - это синтаксис деревьев из идентификаторов и констант. Кроме того, от лиспа мы возьмём статическое МП. Т.е., у нас будет не только c::defun (определение с-функции) и не только с::typedef. Но и defmacro, обычное лисповое defmacro, которое заменит #define. Также у нас будет лисповый класс c-type (который уже есть в разных реализациях лиспа в связи с FFI). Также у нас будет парсер сишных заголовочных файлов, чтобы мы могли "заинклюдить" сишный код в наш лисповый код. Такой парсер в разных реализациях лиспа тоже есть.

Зачем это нужно? Например, чтобы писать более удобно, чем на С, программы, которые обычно пишутся на С.

★★★★

Re: lisp как препроцессор для C

Ежик, выдыхай :)

imp ★★ ()

Re: lisp как препроцессор для C

Приведи лучше пример кода для такого case'а (LISP macro definitions + C-code) -- очень любопытно взглянуть :).

kondor ★★★ ()

Re: lisp как препроцессор для C

Пример функции на C и её вида в лиспе:

void * xmalloc (size_t size)  {
       register void *value = malloc (size);
       if (value == 0) fatal ("virtual memory exhausted");
       return value;
      }

и два варианта лиспового представления: 

1. Более близкое к С. Здесь конструкции лиспа изменены. В них предусмотрено место для декларации типа

(c::defun void* xmalloc ((size_t size)) { 
  (let1 (void* :register t) value (malloc size)
    (when (== value 0) (fatal "virtual memory exhausted"))
    value))

2. Более лисповое. 
(c::defun xmalloc (size)
  (declare (ftype (function (size_t) void*) xmalloc)
  (let1 value (malloc size)
    (declare (register value)) ; такой декларации пока в лиспе нет
    (declare (void* value)) ; хотя можно сделать type inference
    (when (== value 0) (fatal "virtual memory exhausted"))
       value))

В обоих случаях применён макрос let1, который означает "let только с одной переменной" - экономится 4 скобки. Вот его определение:

(defmacro let1 (var init &body body) `(let ((,var ,init)) ,@body)) 
    

den73 ★★★★ ()

Re: lisp как препроцессор для C

> Зачем это нужно? Например, чтобы писать более удобно, чем на С, программы, которые обычно пишутся на С.

Я не знаю, зачем это нужно, т.к. SBCL с (declare (optimize (speed 3) (safety 0) (space 0))) генерирует машинный код не слишком хуже, чем gcc.

mv ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от mv

Re: lisp как препроцессор для C

mv, конкретный повод - это желание сделать кросс-платформенную разработку под iPhone/Symbian. SBCL туда не протащишь. Ну и вообще, не все программы могут быть по 18 мегабайт :)

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

Не все лисповоды захотят писать на таком "лиспе", в котором много лишних сущностей. Твои примеры больше похоже на FFI'шную обвязку :)

mv ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от mv

Re: lisp как препроцессор для C

mv, я уже вырос из того возраста, когда хотел сделать счастливыми всех. Это - решение для конкретного класса задач, отличного от класса задач лиспа. Ничто не мешает написать какую-то часть программы на этом "лиспе". В котором не то, чтобы лишние сущности - это вообще другой язык, от лиспа у него только синтаксис и МП. В нём, например, не будет интерпретатора и сборки мусора. Не будет и универсального способа вызвать С-функцию из лиспа. Для каждой С-функции нужно будет определить место размещения кода (внешнюю либу или внешний экзешник) и механизм вызова этой либы или экзешника. Если вообще нужно вызывать её из лиспа.

den73 ★★★★ ()

Re: lisp как препроцессор для C

Предлагаю добавить в новый синтаксис русскоязычные идентификаторы из набора языка 1С:Предприятия, чтоб сковородку пожарче забронировать.

anonymous ()

Re: lisp как препроцессор для C

первое - смотри на http://www.intelib.org

второе - такое вполне себе быстро изготавливается из связки boost preprocessor + boost proto + еще пара библиотек

ott ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от anonymous

Re: lisp как препроцессор для C

Похоже, я плохо объяснил. У нас есть обычный лисп, но он 
используется только как среда для порождения С-программ. Т.е., имеется, допустим, пр-во имен C. Есть lisp:let - обычный let. 
Есть C:let - let для C. При этом, lisp:let подразумевает 

(let ((var value)...) ...)

,но 

(c:let ((с-type var value)...) ... )

Здесь C становится как бы DSL внутри лиспа. Но мы не можем сделать
вызов функции, определённой с помощью c:defun. Можем сделать 
примерно так:
file "macro.lisp":
(defmacro c:let1 ...) 

file "a.lisp"
(defpackage :a (:use "C"))
(in-package :a)
(in-c-program "a.out")
(defun main ((int argc) (char** argv))
  {let1 int i (+ argc 1)
    (printf "%d,%s\n" i [argv 0])
    0}
)

и далее в интерпретаторе:
> (compile-file "a.lisp")
> (port:run-prog "a.out")
> (a::main 1 nil)
ERROR: a::main is undefined

Вот, в общем-то пример использования предполагаемой системы в её минимальном варианте. 

den73 ★★★★ ()

Re: lisp как препроцессор для C

> Зачем это нужно? Например, чтобы писать более удобно, чем на С, программы, которые обычно пишутся на С.

очень слабо себе представляю то же именно будет конечным потребителем этого чуда. лисперы? сомневаюсь. всем двум с половиной лисперам это нафик не нужно. сишники? ещё смешнее.

// wbr

klalafuda ★☆☆ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

Нда, спасибо за intelib.org, уже второй чел мне это сегодня предлагает. Не ошибся я и насчёт того, где и с кем я буду обсуждать эту тему посмертно.

Забавно, что у меня с Андреем Столяровым есть общие знакомые и я видел этот (L|) ещё в автореферате его диссера, на бумаге. И уже тогда мне было ясно, что это - не мой вариант. Когда-то я даже писал ему письмо на эту тему, хотя тогда думал больше про FFI. Но FFI его не торкнуло (и я теперь понимаю, что это было правильно). Забавно и то, что человек, которого я было загрузил темой МП и который мне принёс данный текст, сейчас работает чуть ли не руководителем отдела ИТ, вместо лиспа развлекается Варкрафтом и получает зарплату в 5 раз больше, чем я когда-либо получал. Такова ирония судьбы.

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

А мы всё же пойдём другим путём. Начнём с того, что в Symbian OS С++ весьма неполноценен. Да и вообще, я не люблю С++. Меня от него тошнит. Можно считать это моим закидоном (хотя причины тому вполне объективны и известны).

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

>Да и вообще, я не люблю С++. Меня от него тошнит.

Попробуй D. Там на языке шаблонов можно сцену отрейтрейсить в выходной elf - бинарь.

Absurd ★★★ ()

Re: lisp как препроцессор для C

Лисповское метапрограммирование не только со списками работает, его и просто к строкам можно применять. Так что никаких проблем нет в том, чтобы оставить обычный сишный синтаксис и не тянуть его в С-выражения.

anonymous ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

>> Пример функции на C и её вида в лиспе:

Ни один вменяемый программист на C/C++ такой страшный нечитабильный ужас не станет использовать.

mironov_ivan ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от mironov_ivan

Re: lisp как препроцессор для C

>> Пример функции на C и её вида в лиспе:

>Ни один вменяемый программист на C/C++ такой страшный нечитабильный ужас не станет использовать.

Программист на С++ по поводу страшного нечитаемого синтаксиса не имеет морального права даже заикаться.

Absurd ★★★ ()
Ответ на: Re: lisp как препроцессор для C от Absurd

Re: lisp как препроцессор для C

>> Программист на С++ по поводу страшного нечитаемого синтаксиса не имеет морального права даже заикаться.

Да, да, да... Common lisp - самый читабельный, удобный, простой и понятный ЯП, подходящий для любых задач. А C++ - это неюзабельное говно для быдла, неосилившего CLisp.

mironov_ivan ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от mironov_ivan

Re: lisp как препроцессор для C

Вообще-то этот синтаксис для кода, который генерится автоматически, а не живым человечишкой.

anonymous ()
Ответ на: Re: lisp как препроцессор для C от mironov_ivan

Re: lisp как препроцессор для C

>А C++ - это неюзабельное говно для быдла, неосилившего CLisp.

Для тех кто вынужден с ним возиться в силу разных причин. Поэтому для новых проектов лучше подыскать что-либо менее эзотерическое.

Absurd ★★★ ()
Ответ на: Re: lisp как препроцессор для C от anonymous

Re: lisp как препроцессор для C

Нешустрый интерпретатор Lua от метапрограммирования сильно более шустрым не становится, увы. А так - Лисп, но "с синтаксисом", для особо трусливых, которые боятся S-выражений.

anonymous ()
Ответ на: Re: lisp как препроцессор для C от anonymous

Re: lisp как препроцессор для C

> Лисповское метапрограммирование не только со списками работает, его и просто к строкам можно применять. Так что никаких проблем нет в том, чтобы оставить обычный сишный синтаксис и не тянуть его в С-вражения.

Конечно, нет проблем. Есть даже такой проект PLisp. Но это вторично. Первична сама среда CL со всеми её возможностями. И на первых порах неохота, чтобы синтаксис путался под ногами. В лиспе есть квазицитирование, и придётся попариться перед тем, как его удастся приспособить к сишному синтаксису. Для квазицитирования нужно не меньше трёх свободных символов в языке. А в С их просто нету.

Кроме того, возможность писать char* в одно слово - это тоже довольно круто, а это в корне противоречит С-шному синтаксису. Можно, конечно, пойти на компромисс и сделать инфиксную запись, разделяя токены как в лиспе, пробелами, но имхо это только лишний гемор. Лисповую запись вполне можно читать, к тому же есть лисп-мода в редакторе, которая делает работу с лиспом действительно удобной. Достаточно сказать, что s-выражение можно вырезать одной командой. Далеко не в каждой среде для работы с С (ни в одной из виденных мной) подобной команды нет.

Касаемо D. Язык без препроцессора мне не нравится. Тем более, список платформ сразу не нашёл. Нужна вещь переносимая. Что переносимо лучше С? Lua тоже не годится, т.к. интерпретатор.

И давайте больше не будем спорить насчёт С++ и т.п. С++ как вариант не рассматривается, по определению. Лисп не идеален, но он принят за среду разработки, тоже по определению. Более интересны будут вопросы по существу предлагаемого решения. Может быть, я не вижу каких-то ужасных грабель?

Ну и самое интересное - это найти попутчиков.

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

> список платформ сразу не нашёл

Теоретически всё, что поддерживает gcc.

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

Legioner ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от jtootf

Re: lisp как препроцессор для C

> http://www.bitc-lang.org/docs/bitc/spec.html ?

В общем-то, за этим языком стоит здравый смысл. Но теоремы о коде - это имхо пока что рановато. Не доросло ещё железо до таких задач. Нужно его ускорить ещё хотя бы раз в сто-тысячу. Тогда можно будет всерьёз говорить о применении этого подхода в практичных языках. Мне кажется, язык этот всё же более академический. Да и его, в общем-то, ещё не существует в природе, судя по документации и версии. Поэтому, спасибо за подсказку, буду иметь в виду, но не более того. Сейчас речь всё же идёт о более прагматичных вещах - внедрении в С полноценного интерфейса к системе типов и полноценного МП времени компиляции.

Всё же, несколько вопросов по этому языку:

Если Вы серьёзно возились с этим языком, есть ли там примитивы, транслирующиеся в сишные "функции с переменным числом аргументов" и setjmp?

Есть ли там поддержка потоков и IPC? Есть ли МП (негигиеничное)?

Если на все вопросы ответ положительный, то это круто и я даже сразу ещё раз более внимательно на него посмотрю.

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

> А вообще не вижу никаких причин просто не писать на лиспе. Какой то изврат вы придумываете.

Причин не писать не лиспе много.

Только один пример: я недавно писал систему для управления печкой. Она открывает/закрывает COM-порт и обращается со звуковой платой. Если пользоваться FFI, то ошибка в последовательности вызовов соответствующих функций может приводить к неприятностям: либо зависает тред, либо какой-то ресурс не освобождается. Бывает и хуже - падает сам лисп. Лисп никогда не должен падать, т.к. он тяжёл, как слон. Ему падать - это очень больно и опасно. Естественным будет вынести такие вещи в отдельный процесс - при смерти процесса ОС всё приводит в порядок. И этот процесс вряд ли должен быть написан на CL.

Вторая причина - мобильные системы - я сразу об этом написал.

Мобильное приложение хочет состоять из двух частей - переносимое ядро и непереносимые драйвера/линки к ГУИ. На чём писать переносимое ядро? В мобильных приложениях скорость и компактность работы - это важное преимущество. Например, С намного лучше Явы, там, где С вообще есть. Имеется платформа Symbian (кастрированный C++) и iPhone (ObjC). Общий знаменатель у них - это С.

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от ACR

Re: lisp как препроцессор для C

Absurd, спасибо за D. Будем смотреть более подробно. Похоже, что это -действительно тема. Хотя я не совсем понял. В лиспе МП имеет полный доступ ко всей инфраструктуре. Т.е., во время компиляции можно делать ровно всё то же, что и во время выполнения программы (т.к. компиляция - это тоже выполнение программы). Ограничения имеются на результат вычисления и на доступную информацию о компилируемой программе, но не на само вычисление. В частности, я могу запросить пользователя во время компиляции, вызвать внешнюю программу, обратиться к любым структурам данных, описывающим конфигурацию. Доступно ли это в D?

ACR, насчёт Scheme я думаю. Мне не нравится в Scheme её недостаточная прагматичность. Огромная польза лиспа - это &key, &optional, &body (негигиеничные макросы). Также очень здорово наличие (в стандарте) пр-в имён. Оптимизации в CL тоже гораздо более доступны и многообразны, в результате чего код получается на порядок быстрее. Хотя для метасредства скорость не столь критична. Не нравится наличие нескольких конкурирующих макросистем, не нравится попытка навязать гигиену (с defmacro и gensym в лиспе куда как лучше и при минимальном навыке наступить на грабли практически невозможно).

Хотя, возможно, я просто плохо знаю Scheme и пр-ва имён уже появились. С другой стороны, Scheme без вопросов встраивается даже в довольно небольшие программы, в отличие от CL.

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

> В лиспе есть квазицитирование, и придётся попариться перед тем, как его удастся приспособить к сишному синтаксису. Для квазицитирования нужно не меньше трёх свободных символов в языке. А в С их просто нету.

Ты не понял. Я предлагаю отказаться от списков для представления сишного кода. Строк хватит. Тогда вместо квазицитирования просто (string-append ...)

anonymous ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

Ладно еще один аргумент, лиспом пользуются только вы и еще два три человека в мире, остальные прагматичные люди шарахаются в сторону при одном только упоминании, в то время как perl, php и даже bash имееют куда более широкий круг адептов.

Согласен с тем что вставки в С код вида <?php SomeFun(); ?> выглядят коряво и грамоздко но у них больше шансов на то что на них хотябы кто то посмотрит.

Или для вас это не аргумент?

ACR ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

> Только один пример: я недавно писал систему для управления печкой. Она открывает/закрывает COM-порт и обращается со звуковой платой. Если пользоваться FFI, то ошибка в последовательности вызовов соответствующих функций может приводить к неприятностям: либо зависает тред, либо какой-то ресурс не освобождается. Бывает и хуже - падает сам лисп. Лисп никогда не должен падать, т.к. он тяжёл, как слон. Ему падать - это очень больно и опасно. Естественным будет вынести такие вещи в отдельный процесс - при смерти процесса ОС всё приводит в порядок. И этот процесс вряд ли должен быть написан на CL.

Если писать на С, то писать не много (не сотни тысяч строк), а значит метапрограммирование значимого выигрыша не даст.

> Вторая причина - мобильные системы - я сразу об этом написал.

> Мобильное приложение хочет состоять из двух частей - переносимое ядро и непереносимые драйвера/линки к ГУИ. На чём писать переносимое ядро? В мобильных приложениях скорость и компактность работы - это важное преимущество. Например, С намного лучше Явы, там, где С вообще есть. Имеется платформа Symbian (кастрированный C++) и iPhone (ObjC). Общий знаменатель у них - это С.

Можно компилировать лисп в С. На тех же симбианах куча программ на Java, которая не слишком шустра, тем не менее программы пишутся и используются.

Legioner ★★★★★ ()

Re: lisp как препроцессор для C

Ты не забыл, что лисп - функциональный язык? А C - процедурный. Может я не внимательно прочитал тему, но мне показалось, что ты предлагаешь писать в процедурном стиле, используя синтаксис лиспа. От этого вся его прелесть пропадает, так что в этом нет смысла, имхо.

Laz ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

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

Legioner ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от Laz

Re: lisp как препроцессор для C

> Ты не забыл, что лисп - функциональный язык? А C - процедурный

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

Legioner ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от ACR

Re: lisp как препроцессор для C

> Ладно еще один аргумент, лиспом пользуются только вы и еще два три человека в мире,

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

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

anonymous ()
Ответ на: Re: lisp как препроцессор для C от ACR

Re: lisp как препроцессор для C

> лиспом пользуются только вы и еще два три человека в мире

Источник статистики можно?

Legioner ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от Legioner

Re: lisp как препроцессор для C

В любом случае, мне стандартный синтаксис С кажется более удобным для императивщины, чем лисповский.

Laz ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от Laz

Re: lisp как препроцессор для C

> Может я не внимательно прочитал тему, но мне показалось, что ты предлагаешь писать в процедурном стиле, используя синтаксис лиспа.

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

anonymous ()
Ответ на: Re: lisp как препроцессор для C от Laz

Re: lisp как препроцессор для C

> В любом случае, мне стандартный синтаксис С кажется более удобным для императивщины, чем лисповский.

Фича Лиспа в том, что у него вообще нет синтаксиса.

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

anonymous ()
Ответ на: Re: lisp как препроцессор для C от anonymous

Re: lisp как препроцессор для C

> Фича Лиспа в том, что у него вообще нет синтаксиса.

(if 1 2 3) это не синтаксис что ли? Другое дело, что он динамический, а не статический, это не привычно, но это синтаксис.

Legioner ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от Legioner

Re: lisp как препроцессор для C

> (if 1 2 3) это не синтаксис что ли? Другое дело, что он динамический, а не статический, это не привычно, но это синтаксис.

Синтаксис есть у S-выражений, а не у Лиспа.

Точно так же, как синтаксис есть у XML, но нет, например, у SOAP.

anonymous ()
Ответ на: Re: lisp как препроцессор для C от anonymous

Re: lisp как препроцессор для C

> Синтаксис есть у S-выражений, а не у Лиспа.

А почему есть название syntactic keywords?

Legioner ★★★★★ ()
Ответ на: Re: lisp как препроцессор для C от Legioner

Re: lisp как препроцессор для C

> А почему есть название syntactic keywords?

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

anonymous ()
Ответ на: Re: lisp как препроцессор для C от anonymous

Re: lisp как препроцессор для C

> Можно компилировать лисп в С

Legioner, будет сборка мусора и издержки динамической типизации. Известно, что код пишется путём переделывания чужих примеров. Возникнет проблема перевода этих примеров с С на Лисп (в моём подходе эта проблема тоже есть, но её можно легко и сильно автоматизировать, т.к. нужна лишь замена синтаксиса). Касаемо нестандартных расширений, да, они есть, я знаю. Тут скорее вопрос ограниченности мозгового ресурса. В Схему нужно серьёзно погружаться, чтобы сделать выбор. Конечно, интересна и возможность встроить лисп в С, поэтому, после написания первого прототипа вопрос перехода на Scheme будет рассмотрен очень серьёзно. Тем более, что Scheme вообще более мощный язык, чем лисп, ввиду наличия call/cc.

> Ладно еще один аргумент, лиспом пользуются только вы и еще два три человека в мире

Моя задача не состоит в том, чтобы всех осчастливить. Я уже про это писал. Опен-сорс (для многих) - это средство помочь другим людям работать на себя.

> Я предлагаю отказаться от списков для представления сишного кода. Строк хватит.

Код - это деревья, а не строки. Просто эти деревья плоско написаны на листе бумаги.

den73 ★★★★ ()
Ответ на: Re: lisp как препроцессор для C от den73

Re: lisp как препроцессор для C

Laz, синтаксис и ФП/ИП - вещи ортогональные. Я согласен, что синтаксис С более читаем, но я считаю, что он менее удобен для МП. В остальном, согласен, что главное в лиспе - это макросы. А ФП - это вообще не мой конёк, я к нему совершенно холоден.

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