99 бутылок: HolyC
История появления языка, на котором написана сегодняшняя «песня о пиве», довольно занятна.
Его автор, Терри Дэвис — гениальный одиночка и бывший инженер компании Ticketmaster, который посвятил более десяти лет созданию собственной операционной системы TempleOS. Страдая от шизофрении, он считал, что действует по воле Бога, который лично поручил ему создать «божественную ОС». Несмотря на тяжёлое психическое состояние, Дэвис самостоятельно написал компилятор, ядро, графическую оболочку и язык программирования — в полном одиночестве и с поразительной продуктивностью.
83. HolyC — тот самый язык, разработанный Терри. Выглядит он довольно интересно. Сильно напоминает Си, но имеет много интересных особенностей, некоторые из которых сразу бросаются в глаза, даже в моей небольшой программе.
Во-первых, конечно, это собственная система типов, простая и понятная — значение либо выводится (auto), либо сразу видно сколько бит оно занимает, а так же знаковое оно или нет — U8, I8, U16 и так далее. Тип U0, как легко догадаться — аналог void.
Во-вторых, упрощённый вывод на экран — всё отдельностоящие строки сразу выводятся, всё остальное можно вывести через операцию «запятая», указав формат и значения — одно или несколько.
Чуть менее заметная деталь — оператор case может не иметь аргумента, в таком случае используется автоикрементное значение, начинающееся с нуля. В HolyC вообще довольно много интересного синтаксического сахара.
Поражает, как много может создать в одиночку человек, заражённый какой-то идеей. Работы проделано довольно много, причём, работы проделанной очень хорошо. Я не смотрел внутренности TempleOS, но язык HolyC выглядит как нечто цельное и продуманное. Некоторые конструктивные особенности я был бы рад видеть и в современном Си, например, значения по-умолчанию для параметров функций.
// "99 Bottles of Beer," written in HolyC on July 9, 2025
// by Evgeny Stepanishchev (https://bolknote.ru)
auto Bottle(U8 b)
{
U8 *bottles, *ret;
switch (b) {
case:
bottles = StrNew("No bottles");
break;
case:
bottles = StrNew("1 bottle");
break;
default:
bottles = StrPrint(NULL, "%d bottles", b);
break;
}
ret = StrMerge(bottles, " of beer");
Free(bottles);
return ret;
}
U0 Main()
{
U8 *bottles, b = 99;
while (b) {
bottles = Bottle(b);
"%s on the wall, %1$s!\n", bottles;
Free(bottles);
bottles = Bottle(--b);
"Take one down, pass it around,\n";
"%s on the wall!\n\n", bottles;
Free(bottles);
}
"No more bottles of beer on the wall,\n";
"No more bottles of beer!\n";
"Go to the store and buy some more,\n";
"99 bottles of beer on the wall!\n";
}
ох, удачного дебага!
Сомнительная штука, да :-) Одно значение уберёшь и не заметишь как всё сломаешь.