vak: (Робот 2)
Узнал новое слово в математике: logit. Оно давно существует, но нас такому не учили. Означает вещественное число в диапазоне от -∞ до +∞ и представляет логарифм шанса некоторого события. Если шанс 1:1, то есть пятьдесят на пятьдесят, лоджит будет ln(1/1) = 0.
  • logit = 1 это шанс e:1, или примерно 8:3
  • logit = 2 это шанс где-то 7:1
  • logit = 3 это шанс 20:1
И так далее. Многие ИИ модели возвращают результат именно в лоджитах.
vak: (Daemon)
Штудирую редкую книжку: лекции Фейнмана про компьютеры. Оказывается, он в середине 80-х учил народ уже не физике, а компьютерным вычислениям.



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

vak: (Аристипп)
Перепощу цитату из [personal profile] kanibolotsky, чтобы расставить точки над ы.
...Ответственность не означает вину, а любая вина не обязательно означает вину юридическую или уголовную. Существует и ответственность без вины, существует и моральная вина без уголовной. Я не обвиняю всех русских в том, что они должны нести юридическое или уголовное наказание за преступления российского государства, если сами эти преступления они не совершали. Ответственность же означает не вину, а нахождение человека в ситуации, когда от человека требуется нравственный выбор. Если к порогу Вашего дома принесли младенца, в этом нет никакой Вашей вины, но есть Ваша ответственность. И если человек в этой ситуации поступит морально, т.е. позвонит в полицию и социальные службы, а не оставит ребенка умирать одного на морозе, то никакой вины у него не наступит. Вина наступает только когда, находясь в ситуации ответственного выбора, человек сам поступает неморально, например, оставляет ребенка умирать. Не является виной родится у родителей, которые считаю себя, по своему собственному выбору, русскими и прививают эту идентичность своим детям. Но когда от вашего имени как русского русское государство совершает преступления, у вас появляется ситуация выбора и ответственности, пока еще без всякой вины. И можно в этой ситуации принять моральный выбор и бороться против преступного российского государства. Есть очень достойные и моральные русские люди, которые именно так и поступают. И многие из них сейчас сидят в русских тюрьмах, как и многие достойные и моральные немцы сидели в немецких тюрьмах и концлагерях в Третьем Рейхе. А некоторые уже убиты, и они мученики и герои. Но, с другой стороны, можно сделать и аморальный выбор, т.е. согласиться работать на преступное государство, сотрудничать с ним, распространять пропаганду, исходящую от преступного государства. И тогда ответственность станет виной.
vak: (Украина)
Зря Трамп встал между Давидом и Голиафом. Судьба его будет незавидна.

vak: (Украина)
Не всем оккупантам смерть: некоторые имеют шанс выжить, если вовремя сдадутся.

vak: (Бодхидхарма)
Компилятор Си на Брааме умеет компилировать сам себя. Для демонстрации я сделал отдельный пакет с исходными текстами. Ставится он командами:
pkg update
pkg install csources
Вот как выглядит полный протокол сборки компилятора с исходных тестов.
$ cd /pkg/store/csources*/
$ make
( протокол )
vak: (Українець)
Товарищ утверждает, что протоиндоевропейский язык — первоисточник многих европейских и азиатских языков — зародился в степях Украины.

lexiconvalley.substack.com/p/the-ukrainian-language
vak: (Бодхидхарма)
Готов make для Браама. Я взял версию от Unix v7 за исходную, и добавил все современные фичи от GNU make. Ставится командой "pkg install make".



Описание здесь: make/Manual.md
vak: (Украина)
Професор Київського університету Богдан Рубльов розказує про математику, про Україну та трохи про нашу школу. Ми вчилися з Богданом у паралельних класах. Грали в футбол чимало. Богдан у футболі мастер, супроти мене увальня. 😀

vak: (Гость с планеты Узм)
"Мы строили, строили и наконец построили. Ура!" - как говаривал Чебурашка в известном мультфильме.

Теперь можно программировать на Си прямо в браузере. Я портонул компилятор vcc под Браам. Заходите на braamix.github.io и запускайте:
pkg update
pkg install cc

Скомпилируем классический пример.
$ cd /pkg/store/cc-*/share/
$ cat hello.c
// hello — the smallest program: `cc hello.c && ./a.out`.
#include <stdio.h>

coro(braam_call *) int main(int argc, char **argv)
{
await printf("Hello, %s!\n", argc > 1 ? argv[1] : "world");
return 0;
}
$ cc hello.c -o hello
$ ./hello
Hello, world!
$ ./hello Braam
Hello, Braam!

Заметьте, что программа отличается от классического Си. Потому что в браузере все вызовы неблокирующие, на корутинах.

Размер рантайма вполне скромный.
$ size hello
text data bss dec hex filename
23614 605 0 24219 5e9b hello

И да, этот компилятор может компилировать сам себя. Согласно традиции.
vak: (Бодхидхарма)
Хорошему компилятору вменяемые сообщения об ошибках не помешают.



Я добавил в vcc сообщения об ошибках в стиле, похожем на gcc.
vak: (Бодхидхарма)
Где могут быть полезны корутины? Где нужна кооперативная многозадачность без многоядерности. Сетевые запросы, диск, сокеты, таймеры, обращения к базе данных, игровые боты, парсеры, движки рабочих процессов и анимационные последовательности. Некоторые задачи красиво ложатся на корутины.

Вот, к примеру, классическая задачка про пять обедающих философов.

Каждый философ либо думает, либо кушает.
coro(int) void philosopher(int i)
{
int think = 1; // everyone gets hungry at once

for (;;) {
state[i] = 'T';
yield think;
state[i] = 'H';
while (!await try_to_eat(i))
yield rnd(1, 3); // back off, then try again
think = rnd(1, 4);
}
}
Для еды философу нужны две вилки, ведь на столе спагетти. Если вилки взять не удаётся (заняты соседями), философ ждёт.
coro(int) int try_to_eat(int i)
{
int left = i, right = (i + 1) % N;

await take(left, i);
defer put(left);
if (!await try_take(right, i))
return 0; // put(left) runs here
defer put(right);

state[i] = 'E';
meals[i]++;
yield rnd(1, 3); // eat
return 1; // put(right), then put(left)
}
Весь исходник программы здесь: dining-philosophers.c

Под gcc или clang корутины недоступны: вам понадобится компилятор vcc. Собираем и запускаем программу:
$ vcc dining-philosophers.c -o dining-philosophers
$ ./dining-philosophers
tick 0 1 2 3 4 forks
0 T T T T T .....
1 E H E H H 00224
2 E H T H H 00.3.
3 E H T E H 00.33
4 T E H T E 411.4
5 T T E T E 4.224
6 H T E T T ..22.
7 E H T E T 00.33
8 E H T T T 00...
9 E H T E T 00.33
10 T E T T E 411.4
11 H T E H T ..22.
12 E T E H H 00224
13 E H E H H 0022.
14 T H T E H .1.33
15 H E H E H 01133
16 H E H E H .1133
17 H T H T E 4.2.4
18 H T E H E 4.224
19 H T T H E 4..34
20 H E T H T .11..
21 H E T E T 01133
22 H E H E T .1133
23 H T H T E 4.2.4
24 H T E T E 4.224
25 H H E H T .122.
26 H H E H H 0.224
27 E H T H H 00.3.
28 E H T E H 00.33
29 T E H E H .1133
30 T T H T E 4.2.4
31 H T E T E 4.224
32 H H E T T .122.
33 H H T T T 0....
34 E H T E T 00.33
35 T H T T E 4...4
36 T E T T E 411.4
37 H T E H T ..22.
38 E H E H T 0022.
39 E H T E H 00.33
meals: 6 6 7 8 6
forks still held after the table is cleared: 0

Я доработал компилятор, теперь корутины доступны на всех платформах. На Линуксе и маке, x86_64 и arm и riscv - везде.
vak: (Линукс)
LiteIX - ставится на любой 386/486 с памятью от 8 Мбайт, в режиме консоли. Для запуска графического интерфейса X Windows надо 32 Мбайта.

vak: (Daemon)
В компиляторе vcc я добавил корутины в язык Си. Пока только для Браама. К примеру, так выглядит аналог команды /bin/cat, которая переписывает вход на выход:
#include <coro.h>
#include <stdio.h>
#include <unistd.h>

coro(braam_call *) 
int main()
{
    char buf[512];
    ssize_t n;
    while ((n = await read(0, buf, sizeof buf)) > 0)
        if (await write(1, buf, n) < 0)
            return 1;
    return n < 0;
}
Подробное описание этой фичи здесь: Coroutines_in_C.md
vak: (Бодхидхарма)
Компилятор vcc теперь на Линуксе и маке по умолчанию создаёт родные бинарники. Например:
$ vcc hello.c 
$ ./a.out
Hello, World!
Заглянем "под капот", какие проходы при этом выполняются.
$ vcc -v hello.c 
/home/vak/.local/bin/vcpp -t x86_64-linux -nostdinc -I/home/vak/.local/share/vcc/x86_64-linux/include hello.c /home/vak/.tmp/vccKpzN1K.i 
/home/vak/.local/bin/vparse /home/vak/.tmp/vccKpzN1K.i /home/vak/.tmp/vccmb65nv.ast 
/home/vak/.local/bin/vlower -t x86_64-linux /home/vak/.tmp/vccmb65nv.ast /home/vak/.tmp/vccuuoSdo.tac 
/home/vak/.local/bin/vgenx86 --linux /home/vak/.tmp/vccuuoSdo.tac /home/vak/.tmp/vccb2Q3rw.s 
/usr/bin/gcc -c -o /home/vak/.tmp/vcclcl2h5.o /home/vak/.tmp/vccb2Q3rw.s 
/usr/bin/gcc -no-pie -o a.out /home/vak/.tmp/vcclcl2h5.o -L/home/vak/.local/share/vcc/x86_64-linux/lib -lvcc 
Сначала препроцессор, получаем файл *.i. Затем парсер преобразует его в *.ast. После этого собственно компилятор перемалывает программу в *.tac. Дальше кодогенератор порождает код на ассемблере *.s. Потом стандартные ассемблер и линкер, через gcc. Компилятор успешно компилирует сам себя. При этом размер бинарников x86 выходит даже меньше, чем через gcc. Вот, к примеру:
$ size lower parse self/lower self/parse 
   text	   data	    bss	    dec	    hex	filename
 409812	   5456	    280	 415548	  6573c	lower
 181580	   2712	   3312	 187604	  2dcd4	parse
 339664	   6369	    280	 346313	  548c9	self/lower
 151594	   2673	   3232	 157499	  2673b	self/parse
На Линуксе arm64 ситуация не настолько удачная. Есть ещё где потрудиться над оптимизацией:
$ size lower parse self/lower self/parse 
   text	   data	    bss	    dec	    hex	filename
 348687	   5552	    192	 354431	  5687f	lower
 178356	   2880	   3208	 184444	  2d07c	parse
 413957	   6409	    240	 420606	  66afe	self/lower
 179543	   2713	   3208	 185464	  2d478	self/parse
vak: (Daemon)
Я когда-то рассказывал про MMIX - компьютерную архитектуру, изобретённую лично Дональдом Кнутом. Все классические алгоритмы в своём бессмертном многотомнике он программирует на ассемблере этой машины. Народ для неё уже массу софта сварганил, вплоть до Линукса.

Мой компилятор был бы неполным без бэкенда для MMIX. Скомпилируем и запустим стандартный пример.
$ vcc -t mmix hello.c -o hello
$ mmix hello
Hello, World!
[exit 0]
Глянем на ассемблерный код.
$ vcc -t mmix -S hello.c
$ cat hello.s
...
main:
get $0, rJ
geta $2, _str0
pushj $1, printf
setl $1, #0
put rJ, $0
set $0, $1
pop 1, 0
Не могу сказать, что система команд MMIX сильно понятная. Сравнить с другими архитектурами можно здесь: 1595864.html.
vak: (Daemon)
За выходные кавалерийским наскоком я залудил в Си компиляторе кодогенераторы для семи архитектур: Ну и 48-битная бэсм6 никуда не делась. Задача была убедиться, что технология разработки самого компилятора достаточно универсальна и покрывает весь спектр потребностей. Покажу как выглядит код.

Intel x86_64:
$ vcc -t x86_64 -S hello.c
$ cat hello.s
...
main:
subq $8, %rsp
leaq _str0(%rip), %rdi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
ret
( +6 )
vak: (Бодхидхарма)
Для отладки Си компилятора под MSP430 нужен симулятор. Чтобы запускать бинарник и видеть выдачу, в том числе и с трассировкой. Я поискал, нашёл несколько проектов:
В результате взял исходники от Rudolf Geosits и переиначил как надо. Добавил недостающие команды (dadd), вычистил баги (jmp), добавил трассировку. Встроенный интерактивный отладчик оставил, хотя мне он без надобности.

Исходники здесь: sergev/mspsim
  • Всё написано на Си.
  • Вызывается из командной строки.
  • Может непосредственно выполнять бинарники, собранные стандартным msp430-gcc.
  • Умеет трассировку.

Кто не в курсе, напомню: msp430 это та же система команд, что и pdp11, но для современных микроконтролеров. Описание системы команд: MSP430_Instruction_Set.md.

Работает оно так:
$ msp430-elf-gcc -mcpu=msp430 -msim hello.c -o hello
$ mspsim hello
Loaded hello: 5918 bytes, 205 symbols, start at 0x052e
Hello, world!

[Exit code 0 after 3978 cycles]