LINUX.ORG.RU

c3c 0.7.6

 c3, , , ,


1

5

4 октября состоялся выпуск 0.7.6 кроссплатформенного компилятора и стандартной библиотеки языка программирования C3.

C3 – это эволюция, а не революция: язык, похожий на C, для программистов, которые любят C.
C3 – это язык программирования, основанный на синтаксисе и семантике языка C, с целью его развития при сохранении привычности для программистов C.
Благодаря полной ABI-совместимости с C, можно без труда смешивать C и C3 в одном проекте. В качестве демонстрации, vkQuake был скомпилирован с небольшой частью кода, преобразованной в C3 и скомпилированной с помощью компилятора c3c.

Компилятор написан на языке C с использованием фреймворка LLVM (поддерживаются версии 17-22) и распространяется по лицензии GNU LGPL.
Стандартная библиотека распространяется по лицензии MIT.

Основные изменения:

  • Добавлена compile-time функция lengthof().
  • Добавлена поддержка документирующих комментариев к отдельным членам структур, определениям ошибок и значениям перечислений.
  • В $defined теперь можно использовать $alignof, $offsetof и $nameof.
  • Вывод общих параметров lhs -> rhs, например List{int} x = list::NOHEAP.
  • Объединение generic- и обычных пространств имён модулей.
  • env::PROJECT_VERSION теперь возвращает версию в project.json.
  • Теперь работает сравнение слайсов и массивов пользовательских типов, реализующих оператор ==.
  • Добавлены опции оптимизации loop-vectorize, slp-vectorize, unroll-loops и merge-functions.
  • Добавлен вывод времени выполнения $exec при использовании опции -vv.
  • Добавлен оператор +++=.
  • Другие исправления ошибок и улучшения стандартной библиотеки.

>>> Подробности на GitHub

★★★★★

Проверено: Dimez ()
Ответ на: комментарий от lenin386

ls -Al ./hello_world_any
Постеснялись?

Да нет, просто не стал уменьшать размер шрифта.

Вот не меньше сотни мегабайт, конечно жэ.

Типичное «не читал пробовал, но всё равно говно».

c3c compile -vv hello_world_many.c3
...
--------- Compilation time statistics --------

Frontend -------------------- Time --- % total
Initialization took:      2.027 ms       0.6 %
Parsing took:            36.049 ms      10.6 %
Analysis took:           36.100 ms      10.7 %
TOTAL:                   74.176 ms      21.9 %

Backend --------------------- Time --- % total
Ir gen took:             44.984 ms      13.3 %
Codegen took:           177.693 ms      52.5 %  (8 threads)
Linking took:            41.848 ms      12.4 %
TOTAL:                  264.525 ms      78.1 %
----------------------------------------------
TOTAL compile time: 338.701 ms.
----------------------------------------------
stat hello_world_many

Size: 639216

c3c compile -Os hello_world_many.c3`
stat hello_world_many`

Size: 102768

c3c compile -Os -g0 hello_world_many.c3`
stat hello_world_many`

Size: 40456

А вот hello_world_nolibc.c3 без libc:

fn void print(String msg)
{
    $$syscall(1, 1, (uptr)msg.ptr, msg.len); // __NR_write, STDOUT
}

fn void printn(String msg)
{
    print(msg);
    print("\n");
}

fn int main()
{
    printn("Hello, LOR!");
    return 0;
}

fn void _start() @export("_start")
{
    int ret = main();
    $$syscall(60, ret); // __NR_exit
}
c3c compile --use-stdlib=no --link-libc=no -g0 hello_world_nolibc.c3
stat hello_world_nolibc

Size: 2464

strip hello_world_nolibc
stat hello_world_nolibc

Size: 2048

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

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

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

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

ой-вэй! то есть, критику мы воспринимаем болезненно.

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

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

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

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

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

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

а это поделие, скорее всего, к одной платформе прибито гвоздиками для обивки диванов.

Уровень экспертизы я смотрю зашкаливает.

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

чтоб ты кланялся каждый раз лбом об мостовую когда кто-нибудь пишет fn где вас берут таких, удивительны

fr bruh

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

Не спорю. Я бы с огромным желанием перешел бы на Vala, будь что то типа Qt/Vala и поддержка в какой нибудь IDE плагином. Но только прошло 5 лет и до сих пор ничего нет. Люди разработали мощный транслятор и очень классный язык, но с его пригодностью пока…

Пока мне проще взять привычный Qt/C++ и всё будет работать, память не течет, не сегфолтится. Пока нет достаточного импульса чтобы взять и перейти на этот экзотический стек

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Вала прибита гвоздями к glib и его ответвлениям. Тут увы. а язык мне нравится, я на нем прошареный декомпилятор писал но запоролся на парсер исходников. Он был нужен чтоб узнавать обратно конструкции всякие хитрые.

ckotctvo
()
Ответ на: комментарий от I-Love-Microsoft

Вообще вала вроде бы может быть standalone. Но не уверен что там нет подводных камней

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

синтаксис у сишки самый простой

Это у сишки-то самый простой? 8-()

double (*f(int len, double (*vecp)[3]))[3];

Как это разобрать руками, я понимаю, но только потому, что тут один идентификатор. А их сишечка не запрещает и больше одного впиндюрить, даром что все, кроме одного, никакой смысловой нагрузки нести не будут — этот один, который собственно описываемый, ещё найти надо.

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

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

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

Парсер к этому выглядит проще чем ручное разбирание этих объявлений.

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

Парсер к этому выглядит проще чем ручное разбирание этих объявлений.

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

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

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

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

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

в K&R но 2nd ed спецом подпункт спиральки разбора засхематозен

а так да будь все хрени с одной стороны было бы проще (пост только либо пре только -фиксные) - дык эт же структурный асм и не ну на сложно-сложно-сочинённые предложения в эфир пускать когда для 95% и слова лишние

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

палочный счёт прост => с какой-нибудь математикой нигде не облажаться

поэтому и позиционые нотации счисления зарулили и в практике (но не сразу :) )

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

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

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

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

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

Что на один плюс лучше, чем С++.

Теперь понятно, что означает цифра 3 в названии. :)

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

Так вот, терминал, который сумеет нормально отобразить весь юникод, у него как раз в зависимостях и будет вся Убунта

Дамы и господа, «терминал, у которого в зависимостях вся Убунта»:

https://aur.archlinux.org/packages/rxvt-unicode-truecolor-secondaryscroll-clear

Осталось найти там всю Убунту.

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

Чел конечно херню гонит про «сотни мегабайт», но Hello World на 40 килобайт это всё равно так себе результат.

Да и время компиляции 338 ms - отстой.

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

Мне эстетически не доставляют удовольствия эти толпы языков, построенных поверх LLVM, которые пытаются наяривать абстракции а ля «макросы, комптайм вычисления» и т.п. ради самих этих макросов и комптайм вычислений.

В этом нет… стиля. Нет эстетики. Нет вызова. И нет идеи. Подъедать объедки за корпорациями под соусом «нового ЯП», ну такое.

Иными словами: https://vk.com/video-220754053_456240253

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

Для сравнения скорость компиляции исходника на Паскаль-подобном языке в ассемблерный листинг:

$ ./measure_compilation_speed.sh 
total_lines         = 378510
total time          = 1.570
time per repetition = 0.052
lines per second    = 241089
$ grep 'model name' /proc/cpuinfo | head -1
model name	: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz

(Исходник компилируется 30 раз и измеряется общее время.)

52 мс на i5-2450M, чтобы прожевать исходник размером 12617 строк.

P.S. При чем там еще и код 32-битный, что медленнее 64-битного.

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)

Вот этот подход, «у нас новый язычок… у которого 300 мегабайт зависимостей от Эппловского компилятора»:

package-query -Qi -f '%n - %3' llvm llvm-libs
llvm - 122036537
llvm-libs - 157294393

Да нету у вас язычка. У вас нет собственной независимой референсной реализации, которая показывала бы идею, суть и смысл языка и была ценна сама по себе, без приписки на сайте «использует LLVM в качестве бэка».

Это даже хуже, чем Vala, потому что Vala в код на Си транспилируется, а код на Си это лингва франка, которую понимают куча разных компиляторов.

Раньше было модно плееры писать, а теперь языки для LLVM.

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

Ты еще и читать не умеешь. По ссылке лежит патч.

А если достаточно вывода нецветных emoji, то справится и вовсе обычный советсткий xterm.

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

Совпадение. У тебя фонт, содержащий этот символ просто установлен по умолчанию. Настоящая поддержка юникода подразумевает поиск символа в фонтах, если его в текущем Фонте нет.

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

и т.п. ради самих этих макросов и комптайм вычислений.

Это уже луддизм. Комптайм вон делает O(n)-алгоритм парсинга JSON -> структуры. Вполне себе эстетика.

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

Ничего, кроме гноме-терминала из последеней убунту, не работает

У меня всё работает: qterminal, lxterminal, lilyterm, terminology, xterm, патченный urxvt.

Заканчивай чушь писать.

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

Что такое «O(n)-алгоритм парсинга JSON -> структуры»? Конкретнее плиз.

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

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

Кто «вы»?

Я в нулевых перешел на Debian как основную ОС, потому что в ней удобнее было работать, чем в WinXP.

Потом узнал о существовании Arch Linux, который оказался намного проще в управлении, чем Debian.

Так с 2011-го и пользуюсь Arch.

Никаких 2% на десктопе я не занимал, и ложечки украл тоже не я.

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

Если строка времени исполнения, то что ты собрался компилировать в ней?

Строка времени исполнения.

Структура времени компиляции.

const Place = struct { lat: f32, long: f32 };

const parsed = try std.json.parseFromSlice(
    Place,
    allocator,
    \\{ "lat": 40.684540, "long": -74.401422 }
,
     .{},
);
sarumeister
()
Ответ на: комментарий от sarumeister

И зачем тут что-то компилировать?

JSON парсится и записывается в структуру. На Си вокруг либы, парсящей JSON, делается тривиальная обертка из макросов, которая сопоставляет название поля JSON, смещение в структуре и тип данных.

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

Результат в машкодах - одинаковый.

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

Зачем? Это несущественная абсолютно вещь. Костыли из макросов для подобных вещей любой сишник писал.

Ключевое в моём посте: Результат в машкодах - одинаковый.

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

При чем для такой рефлексии не нужен никакой LLVM на 300 метров. Этим всем фронтэнд компилятора занимается.

Покажите технологию и её преимущества в чистом виде, а не городите абстракции на абстракциях поверх чужого огромного фреймворка.

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

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

Вот с этого и стоило начинать.

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

Ключевое в моём посте: Результат в машкодах - одинаковый.

Это спекуляции.

Если же в машкодах получается бинарь, размером в 5-10 раз больше, чем должно быть,

Не знаю, что там должно быть. Плохо написанный парсер JSON будет тормозить в рантайме.

При чем для такой рефлексии не нужен никакой LLVM на 300 метров

90MiB в архиве. С исходниками всей стдлибы.

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

Ну да, да.

- Какой хороший автомобиль!
- Правда? Куплю такой. Опс, Не едет. Что делать?
- курсы авмобильной грамотности. Гараж. Отвёртка.

Идеи СССР не так плохи.

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

Это спекуляции.

Это здравый смысл.

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

Плохо написанный парсер JSON будет тормозить в рантайме.

  1. Парсер JSON не имеет прямого отношения к заполнению структуры данными из JSON. Парсер JSON - парсит JSON. Напишите его хорошо, либо возьмите готовую хорошую реализацию, их полно.
  2. Что он будет тормозить - это бабушка надвое сказала. Обычно в программах тормозят совсем не «парсеры JSON», не «парсеры форматных строк» и т.п. Тормозит плохо написанный прикладной код с херовыми O-большое показателями. Еще бывает, что тормозит ввод-вывод. Или задача плохо распараллелена на потоки. Или тормозят неоптимальные запросы в СУБД. Прежде чем оптимизировать, надо понимать, что именно.
wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

построенных поверх LLVM

Как будто есть другая альтернатива с такими же возможностями и с такой же лицензией.

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

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

Признаюсь, до сегодня парсинг JSON в структуры у меня был сделан плохо (какая-то часть веб-сервиса на С++, sax на RapidJSON). Соответственно, как должно быть правильно — могу единственно подсмотреть в стд зига (lib/std/json/static.zig). Посмотрел, мне понравилось. С точки зрения си-программиста, некоторые фичи я бы поленился реализовать на макросах (если бы вообще смог). Реализация прямолинейная, я думал будет сложнее. Также выяснил, что оптимизации в плане сопоставления полей делает LLVM, а не комптайм.

Делюсь ссылкой на годболт со своим финальным экспериментом. Бинарь в таком виде получился порядка 60к.

https://godbolt.org/z/v6vr6EfaK

Обычно в программах тормозят совсем не «парсеры JSON»

Перечисленные тормоза out-of-scope. Здесь оценивается JSON->структуры.

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

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

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

Вот соответствующий фрагмент:

https://github.com/ziglang/zig/blob/2aea7a42b085f1775889f9d49141faa8098221f9/lib/std/json/static.zig#L353

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

Время парсинга - O(N * M), где N - количество полей в структуре, M - количество записей во входном тексте.

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

Тогда множитель N снижается до log N - время поиска в дереве.

Но в Zig этот способ не реализован.

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

Вполне себе эстетика.

Эндрю Келли писал про HashMap с O(1) поиском в 2018 году. С некоторым везением можно обойтись без дерева.

https://andrewkelley.me/post/string-matching-comptime-perfect-hashing-zig.html

Был ли этот код в прошлом в стд — не знаю, и быстро не проверю. Если бенчмарки не показали преимущества (а они скорее всего не показали преимущества на пк), то что ж, немного жаль.

sarumeister
()
Последнее исправление: sarumeister (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.