Статья посвящена системному программированию на русском языке с C-подобным синтаксисом. Компилятор для языков программирования РУСИ, РУСИ++ и объектный-РУСИ создан путём модификации и пересборки компилятора GCC 14й версии с превращением его в полноценный русско-английский билингвальный компилятор. Отдельно дана инструкция модификации русской раскладки клавиатуры для добавления в неё фигурных, угловых и квадратных скобок - дабы не переключаться и не терять поток.
Оглавление
Предыстория
В предыдущей статье был описан концепт билингвального самособирающегося компилятора языка Си, в котором кириллица уравнялась с оригинальным синтаксисом и можно писать на русском и английском Си одновременно. Код, напомню, выглядит так:
// Английский main с русским типом и оператором int main() { int x = 42; if (x == 42) { возврат 0; } return 1; } // Полностью русский синтаксис цел главн() { цел ъ = 42; если (ъ == 42) { возврат 0; } возврат 1; } // Смешанный стиль цел main() { printf("Легкоступов! Ты чего написал?"); возврат 0; }
Создан он был на базе chibicc для написания на нём кириллического ассемблера КВС https://xn–d1alm1bt.xn–p1ai/administrator/kvs. По сути, это был путь к своеобразной концептуальной полноте: кириллический ассемблер на кириллическом же Си. И для той задачи это было идеальным решением. Минималистичный русский компилятор под Linux. Ничего лишнего. Байты в бинарь складывать может. Задачу свою решает.
Но далее пошли предсказуемые комментарии со сравнениями с бухгалтерским программированием, предложением добавить падежи и пожеланиями не использовать это в продакшене. Обоснование последнего не осталось без внимания.
И действительно: во «взрослых» компиляторах есть ряд преимуществ как маркеров качества - множественное покрытие тестами и 40 лет ассемблерных оптимизаций. И как человек, пишущий свой ассемблер, я на это обратил внимание. Это тысячи человеко-лет работы, сотни оптимизационных проходов, отладка на миллионах строк кода.
Гипотетически: каким бы был полноценный продакшеновый русский Си?
Из спортивного интереса я решил попробовать. Смогу ли оседлать GCC и сделать его билингвом? Ранее мне поддались pascalABC.NET, Blaise и PHP. Вшивал я в них великий и могучий с целью поизучать на практике компиляторостроение. Отличный метод обучаться, кстати.
Получилось. Компилятор, в котором русские и английские ключевые слова - синонимы. Можно использовать любой язык или их гибрид. Реализовано так же, как в исходной статье. Даже тесты взял из русифицированного chibicc.
GCC сложнее, чем chibicc. Множество стандартов Си, поддерживаемых им, не могли не наложить свой отпечаток на его внутреннюю архитектуру.
Что получилось: RUSI на GCC 14.2.0. Русский Си, который компилируется в тот же самый машинный код, что и английский Си. С теми же оптимизациями. С той же производительностью.
Побочными продуктами получились РУСИ++ и объектный-РУСИ.
Зачем это всё
Эрик Рэймонд, «Собор и Базар» (1997), предисловие:
«Every good work of software starts by scratching a developer’s personal itch.»
Точный перевод: «Каждая хорошая программа начинается с того, что разработчик почесал свою личную нужду».
И где-то в России программист решил создать то, что считает нужным. И создаёт.
Линус Торвальдс, предисловие к книге Пекки Химанена «Хакерская этика и дух информационной эры» (2001):
«Linux был в значительной степени хобби (но серьёзным, лучшим из всех).»
Это не «продукт». Не «стартап». Не «проект для галочки». Хобби, но серьёзное. Работа, которая является игрой. Не потому, что «надо», а потому что интересно. Внутренний ребёнок радуется в процессе творчества.
Химанен в книге формулирует суть этики так:
«Хакер - это тот, кто решает проблему, а не тот, кто пользуется готовым решением. Если машина не делает то, что нужно, - хакер открывает её. Если система неудобна - хакер меняет её. Не потому, что заплатили, а потому что интересно. Не потому, что велели, а потому что сам захотел.»
И ведь можно открыть и переделать всё. Компилятор, раскладку, стандарт, технологию, чьё-то мнение.
RUSI - ровно это. Личное творчество. Захотел - переделал. Сделал. Сам захотел - и получилось.
Частично взгляды описаны в предыдущей статье Программисты на Руси программируют на Си. RUSI: Концепт билингвального компилятора.
В конце статьи есть список промптов для анализа текста статьи через призму различных подходов и взглядов.
Где взять и что внутри
Репозиторий: https://github.com/artradeskz/rgcc
Что внутри: GCC 14.2.0 с патчами для русского синтаксиса. Полный diff огромен - здесь не привожу. Но он есть в конце статьи под спойлером.
Краткая выжимка: что именно изменено и зачем.
1. UTF-8 в лексере (libcpp/lex.cc)
Традиционно работая с исходниками, GCC читает не по буквам, а по байтам. Так сложилось исторически. В интернете можно встретить утверждение, что GCC умеет работать с идентификаторами на UTF-8. Про то, что он может так же работать со служебными словами, там не будет сказано. Одна английская буква - один байт. Кириллица же в UTF-8 - это 2 байта на букву. И прежние алгоритмы чтения уже не сработают. Для русификации добавлена обработка UTF-8-последовательностей в forms_identifier_p, чтобы лексер парсил посимвольно, а не побайтово.
if (*buffer->cur == 0xD0 || *buffer->cur == 0xD1) { unsigned char first = *buffer->cur; unsigned char second = *(buffer->cur + 1); if (first == 0xD0 && second >= 0x90 && second <= 0xBF) { buffer->cur += 2; return true; } if (first == 0xD1 && second >= 0x80 && second <= 0x8F) { buffer->cur += 2; return true; } }
2. Синонимы ключевых слов (gcc/c-family/c-common.cc)
Добавлено ~250 русских синонимов в таблицу c_common_reswords[]:
{ "int", RID_INT, 0 }, { "цел", RID_INT_RU, 0 }, { "if", RID_IF, 0 }, { "если", RID_IF, 0 }, { "return", RID_RETURN, 0 }, { "возврат", RID_RETURN, 0 }, { "char", RID_CHAR, 0 }, { "символ", RID_CHAR, 0 },
3. Русские встроенные макросы (libcpp/init.cc)
B("__ФАЙЛ__", BT_FILE, false), B("__ЛИНИЯ__", BT_SPECLINE, true), B("__ДАТА__", BT_DATE, false), B("__СЧЁТЧИК__", BT_COUNTER, true), B("__ВРЕМЯ_ФАЙЛА__", BT_TIMESTAMP, false),
4. Русские директивы препроцессора (libcpp/directives.cc и libcpp/expr.cc)
Директивы препроцессора - это команды, которые начинаются с #. Они не являются частью языка C в том смысле, что парсер их не видит. Их обрабатывает libcpp до того, как парсер получит лексемы. Именно поэтому удалось добавить русские директивы без изменения парсера: достаточно было добавить синонимы в таблицу директив.
В libcpp/directives.cc есть таблица dtable[] - список всех директив. Туда добавлены русские аналоги:
{ do_define, UC"определить", sizeof "определить" - 1, KANDR, IN_I }, { do_include, UC"включить", sizeof "включить" - 1, KANDR, INCL | EXPAND }, { do_if, UC"если", sizeof "если" - 1, KANDR, COND | IF_COND | EXPAND }, { do_endif, UC"конецесли", sizeof "конецесли" - 1, KANDR, COND },
Теперь #включить <stdio.h> работает так же, как #include <stdio.h>. #определить - как #define. #если - как #if. И так далее.
Теперь можно писать:
#если определено(ОТЛАДКА) printf("Отладка включена\n"); #конецесли
Это полный русский аналог английского:
#if defined(DEBUG) printf("Отладка включена\n"); #endif
Немного хулиганства
Чтоб не перепутать стандартный и патченный компиляторы, было бы неплохо иметь возможность различать русифицированный GCC и обычный. Для этого можно доработать вывод команды с информацией о версии компилятора.
Где пропатчить команду gcc --version:
Файл: gcc/gcc.cc, 8900-я строка.
Там зашиты строка копирайта и текст про гарантию. Их можно заменить на свой текст.
if (print_version) { printf (_("%s %s%s\n"), progname, pkgversion_string, version_string); printf ("Copyright %s 2026 Coded by @artrades.\n", _("(C)")); fputs (_("Использовать можно и нужно. Но никто ни за что ответственность не несет(очевидно). This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), stdout); if (! verbose_flag) return 0;
После сборки:
$ gcc --version gcc (GCC) 14.2.0 Copyright (C) 2026 Coded by @artrades. Использовать можно и нужно. Но никто ни за что ответственность не несет(очевидно). This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
В репозитории в данный участок кода - оригинальный. Текст можно менять на свое усмотрение.
Теория: почему русский синтаксис работает
Компилятор - это цепочка преобразований
Компилятор - это сложный многоэтапный механизм превращения слов в исполняемый файл. Это конвейер преобразователей, где каждый этап - это обособленная знаково-логическая система, словно свой отдельный язык программирования.
Упрощённая схема для любого компилятора высокого уровня:
Исходник → лексемы → AST → ассемблер → лексемы → AST → исполняемый файл
Между каждым этапом работает преобразователь со своей логикой.
Что такое «знаково-логическая система»
На каждом этапе есть:
Алфавит - набор допустимых символов
Правила - как из символов строить конструкции
Семантика - что эти конструкции означают
Примеры:
Этап |
Алфавит |
Что описывает |
|---|---|---|
Исходник |
ASCII + UTF-8 |
текст программы |
Лексемы |
TK_INT, TK_IF, TK_RETURN |
ключевые слова, операторы, идентификаторы |
AST |
VarDecl, IfStmt, ReturnStmt |
структура программы |
Ассемблер |
mov, add, call |
инструкции процессора |
Лексемы |
MOV, ADD, CALL, REG_EAX, IMM, MEM |
мнемоники, регистры, непосредственные значения, адреса памяти |
AST |
Instruction(mov, src=REG, dst=REG), Label, Directive(.text) |
инструкции, метки, директивы |
Бинарь |
байты |
готовая программа |
Что изменено
Только первые два преобразования:
Исходник → лексемы (лексер
libcpp)Лексемы → AST (парсер
c-parser.cc)
На этапе первого AST компилятору уже безразлично, как выглядели слова на человеческом языке.
Вот два исходника:
int x = 42;
цел x = 42;
После преобразований оба превращаются в один и тот же узел AST:
VarDecl(name="x", type=Int, init=42)
Дальше компилятор работает только с абстрактным синтаксическим деревом: оптимизирует его, преобразует в ассемблер, в объектный код. Информация о том, что ты написал int или цел, была актуальна лишь на этапе парсера.
Почему производительность идентична
Именно потому, что после AST всё одинаково:
int x = 42; ─┐ ├─ AST - ассемблер - объектный код - линкер - бинарь цел x = 42; ─┘
Русский и английский исходники дают идентичный AST, значит, идентичный ассемблер, идентичный объектный код, идентичный бинарь.
Это подтверждено экспериментально: секция .text (исполняемый код) русского и английского исходников побайтово идентична.
Ключевой вывод
RUSI - это не «новый язык». Это билингвальный фасад к существующему языку C.
GCC научили понимать русские слова на входе, на этапе лексера и парсера. Всё остальное - стандартный GCC 14.2.
Русский синтаксис не добавляет ни одной инструкции в машинный код. Потому что после парсера разницы между русским и английским C не существует, есть только AST.
Сборка: от исходников до установки
Проверено на Ubuntu 26 с установленным в систему GCC 12 или с GCC 15.
Качаем:
git clone --depth 1 https://github.com/artradeskz/rgcc.git
Зависимости:
sudo apt install flex bison libgmp-dev libmpfr-dev libmpc-dev
Или, если не хочется ставить dev-пакеты, используется встроенный скрипт:
cd rgcc ./contrib/download_prerequisites
Он скачает GMP, MPFR, MPC, ISL в дерево исходников:
2026-10-03 18:13:45 URL:https://gcc.gnu.org/pub/gcc/infrastructure/gettext-0.22.tar.gz [26105696/26105696] -> "gettext-0.22.tar.gz" [1] 2026-10-03 18:13:47 URL:http://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.2.1.tar.bz2 [2493916/2493916] -> "gmp-6.2.1.tar.bz2" [1] 2026-10-03 18:13:49 URL:http://gcc.gnu.org/pub/gcc/infrastructure/mpfr-4.1.0.tar.bz2 [1747243/1747243] -> "mpfr-4.1.0.tar.bz2" [1] 2026-10-03 18:13:50 URL:http://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.2.1.tar.gz [838731/838731] -> "mpc-1.2.1.tar.gz" [1] 2026-10-03 18:13:52 URL:http://gcc.gnu.org/pub/gcc/infrastructure/isl-0.24.tar.bz2 [2261594/2261594] -> "isl-0.24.tar.bz2" [1] gettext-0.22.tar.gz: OK gmp-6.2.1.tar.bz2: OK mpfr-4.1.0.tar.bz2: OK mpc-1.2.1.tar.gz: OK isl-0.24.tar.bz2: OK All prerequisites downloaded successfully.
Конфигурация:
mkdir build && cd build ../configure \ --enable-languages=c,c++ \ --disable-multilib \ --disable-nls \ --disable-libgomp \ --disable-libquadmath \ --disable-libssp \ --disable-libvtv \ --disable-libcc1 \ --disable-libmpx \ --disable-libcilkrts \ --disable-libsanitizer \ --disable-isl \ --disable-bootstrap \ --disable-graphite \ --prefix=/usr/local/gcc-rus
Пояснения:
--enable-languages=c,c++- собираем только C и C++--disable-isl- отключает ISL и Graphite--disable-bootstrap- отключен автоматический самосбор(об этом ниже)--prefix=/usr/local/gcc-rus- изолированная установка
Сборка (2 потока, можно и быстрее):
make -j2 2>&1 | tee build.log
На Aspire 5742G - около часа. На современной машине - 15–20 минут.
Установка:
sudo make install
Проверка:
/usr/local/gcc-rus/bin/gcc --version
Добавление в PATH:
echo 'export PATH=/usr/local/gcc-rus/bin:$PATH' >> ~/.bashrc source ~/.bashrc
Тесты из chibicc-rusi
Методика
Взяты тесты из chibicc-RUSI без изменений. Прогнаны на RUSI-GCC.
cd тесты python3 run_tests.py \ --compiler ~/Документы/RUSI++/rgcc/build-full/gcc/xgcc \ --build-dir ~/Документы/RUSI++/rgcc/build-full/gcc \ --dir test_ru \ --verbose
Результат: 63 из 65 (96.9%).
Полный вывод тестов
? Результат прогона тестов
============================================================ ЗАПУСК РУССКИХ ТЕСТОВ ДЛЯ RUSI ============================================================ Найдено тестов: 65 Компилятор: /home/me/Документы/RUSI++/rgcc/build-full/gcc/xgcc Папка сборки (-B): /home/me/Документы/RUSI++/rgcc/build-full/gcc Папка тестов: test_ru [1/65] #else ✓ ОК (код 0) [2/65] alignas ✓ ОК (код 0) [3/65] alignof ✓ ОК (код 0) [4/65] asm ✓ ОК (код 0) [5/65] asm2 ✓ ОК (код 0) [6/65] atomic ✓ ОК (код 0) [7/65] auto ✓ ОК (код 0) [8/65] bool ✓ ОК (код 0) [9/65] break ✓ ОК (код 0) [10/65] case ✓ ОК (код 0) [11/65] char ✓ ОК (код 65) [12/65] const ✓ ОК (код 0) [13/65] continue ✓ ОК (код 0) [14/65] counter_ru ✓ ОК (код 0) [15/65] cyrillic_ident ✓ ОК (код 0) [16/65] cyrillic_ptr ✓ ОК (код 0) [17/65] date_ru ✓ ОК (код 0) [18/65] default ✓ ОК (код 0) [19/65] define ✓ ОК (код 0) [20/65] defined ✓ ОК (код 0) [21/65] do ✓ ОК (код 0) [22/65] double ✓ ОК (код 2) [23/65] elif ✓ ОК (код 0) [24/65] else ✓ ОК (код 0) [25/65] endif ✓ ОК (код 0) [26/65] enum ✓ ОК (код 0) [27/65] extern ✓ ОК (код 0) [28/65] file_ru ✓ ОК (код 0) [29/65] float ✓ ОК (код 3) [30/65] for ✓ ОК (код 0) [31/65] func_ru ✓ ОК (код 0) [32/65] function_ru ✓ ОК (код 0) [33/65] generic ✓ ОК (код 0) [34/65] goto ✓ ОК (код 0) [35/65] if ✓ ОК (код 0) [36/65] ifdef ✓ ОК (код 0) [37/65] ifndef ✓ ОК (код 0) [38/65] include ✓ ОК (код 0) [39/65] inline ОШИБКА КОМПИЛЯЦИИ /usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccvZ6sZh.o: в функции «main»: /home/me/Документы/RUSI++/rgcc/тесты/test_ru/inline.c:7:(.text+0xe): undefined reference to `квадрат' collect2: error: ld returned 1 exit status [40/65] int ✓ ОК (код 0) [41/65] line ✓ ОК (код 0) [42/65] line_ru ✓ ОК (код 0) [43/65] long ✓ ОК (код 0) [44/65] main ✓ ОК (код 0) [45/65] noreturn ✗ ОШИБКА ожидался 0, получен -11 [46/65] once ✓ ОК (код 0) [47/65] register ✓ ОК (код 0) [48/65] restrict ✓ ОК (код 0) [49/65] return ✓ ОК (код 0) [50/65] short ✓ ОК (код 123) [51/65] signed ✓ ОК (код 0) [52/65] sizeof ✓ ОК (код 0) [53/65] static ✓ ОК (код 0) [54/65] struct ✓ ОК (код 0) [55/65] switch ✓ ОК (код 0) [56/65] test_import ✓ ОК (код 0) [57/65] thread_local ✓ ОК (код 0) [58/65] time_ru ✓ ОК (код 0) [59/65] typedef ✓ ОК (код 0) [60/65] typeof ✓ ОК (код 0) [61/65] undef ✓ ОК (код 0) [62/65] union ✓ ОК (код 0) [63/65] unsigned ✓ ОК (код 0) [64/65] volatile ✓ ОК (код 0) [65/65] while ✓ ОК (код 0) ============================================================ РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ ============================================================ Итого: Пройдено: 63 Провалено: 2 Ошибок компиляции: 1 Всего: 65 Успешность: 96.9%
Два «провала» и почему это не баг GCC
inline.c:
// inline.c - Проверка ключевого слова inline инлайн цел квадрат(цел х) { возврат х * х; } цел главн(){ цел рез = квадрат(5); если (рез == 25) { возврат 0; } возврат 1; }
Ошибка линковки: undefined reference to 'квадрат'.
Причина: в C99 inline без static/extern - это внутренняя функция, которая может не создаваться как внешняя. chibicc игнорирует inline и создаёт функцию. GCC следует стандарту и не создаёт. GCC прав.
noreturn.c:
// noreturn.c - Проверка _Безвозврат _Безвозврат пусто завершение() { // Функция помечена как _Безвозврат, но на самом деле возвращается возврат; } цел главн(){ завершение(); возврат 0; }
Падение с SIGSEGV (-11).
Причина: _Noreturn - это обещание компилятору, что функция не вернётся. Если она возвращается, это неопределённое поведение (согласно C11 §6.7.4). chibicc игнорирует _Noreturn. GCC применяет его для оптимизации (выбрасывает недостижимый код). Программа падает. GCC прав.
Вывод
Два «провала» - это не баги GCC, а разница семантики между chibicc и GCC. chibicc не проверяет типы и игнорирует атрибуты. GCC следует стандарту C. RUSI-GCC работает корректнее, чем chibicc-RUSI.
Самосбор
Лучшим способом проверить, что оригинальный Си и Си++ не отвалились, будет сбор GCC самим же собой. После установки в систему это делается аналогичной командой с аналогичной же конфигурацией(см.выше). Затем можно прогнать тесты. Для уверенности можно собрать еще раз.
В отличие от компилятора chibbic, GCC я не стал переписывать на русифицированном Си. Это огромный объем кодовой базы. Однако испытать РУСИ путем вкрапления в исходный код компилятора сам факт выполняемой задачи обязывает. Нужный компилятор в системе есть - можно приступать. Для испытания я выбрал файл gcc/c-family/c-common.cc (таблица ключевых слов).
Две директивы в начале.
#определить GCC_C_COMMON_C #включить "config.h" #include "system.h"
И функцию c_addr_space_name().
/* Return identifier for address space AS. */ конст char * c_addr_space_name (addr_space_t as) { цел rid = RID_FIRST_ADDR_SPACE + as; gcc_assert (ridpointers [rid]); возврат IDENTIFIER_POINTER (ridpointers [rid]); }
С такими изменениями собирать это стандартным компилятором уже не получится!
После сборки можно снова прогнать тесты. И для верности собрать и протестировать еще раз.
При желании можно русифицировать весь код компилятора таким образом, но с практической точки зрения лучше всего начинать переводить стандартные библиотеки: ввод-вывод, работа со строками, математический модуль.
В статье приведена команда для сборки с отключенным бутстрапом. Каждый этап запускается вручную приведенный выше командой. Это сделано чтоб не сломать сборку внутренними тестами, не рассчитанными на задвоенные ключевые слова(-fself-test не даст запустить Stage 2 и Stage 3).
Сравнительные сборки
«Привет, мир»
Исходник у нас будет один, но соберём мы его двумя компиляторами. Содержимое файла:
#включить <stdio.h> цел главн(пусто) { printf("Привет, мир!\n"); возврат 0; }
Обратите внимание: здесь смешанный синтаксис. Директива #включить - русская. Тип цел - русский. Ключевое слово возврат - русское. А printf и stdio.h - латиница, потому что это имена из стандартной библиотеки, их мы не переводим.
Сохраним файл в двух вариантах: привет.си для chibicc (он понимает расширение .си) и привет.c для GCC (он понимает .c). Содержимое одинаковое.
Собираем через chibicc-RUSI:
./rusi.elf -o привет_chibicc привет.си
Собираем через GCC-RUSI (с оптимизацией -O2):
/usr/local/gcc-rus-full/bin/gcc -O2 привет.c -o привет_gcc
Сравнение размеров:
$ stat -c '%n %s байт' привет_chibicc привет_gcc привет_chibicc 17640 байт привет_gcc 15688 байт
$ size привет_chibicc привет_gcc text data bss dec hex filename 1623 933 3 2559 9ff привет_chibicc 949 544 8 1501 5dd привет_gcc
Сведём в таблицу:
Метрика |
chibicc |
GCC -O2 |
Разница |
|---|---|---|---|
Размер файла |
17 640 байт |
15 688 байт |
−11% |
.text (код) |
1 623 байт |
949 байт |
−42% |
.data |
933 байта |
544 байта |
−42% |
.bss |
3 байта |
8 байт |
+5 байт |
Итог (dec) |
2 559 |
1 501 |
−41% |
Файл от GCC на 11% меньше. Но самое интересное - секция .text: код от GCC почти в 2 раза компактнее. .bss чуть больше у GCC, но это 8 байт против 3 - несущественно.
Проверим, что оба работают:
$ ./привет_chibicc Привет, мир! $ ./привет_gcc Привет, мир!
Ответ одинаковый. Теперь посмотрим, почему код от GCC компактнее.
Дизассемблер chibicc-RUSI
0000000000401106 <главн>: 401106: 55 push %rbp 401107: 48 89 e5 mov %rsp,%rbp 40110a: 48 83 ec 10 sub $0x10,%rsp 40110e: 48 89 65 f8 mov %rsp,-0x8(%rbp) 401112: 48 8d 05 f7 2e 00 00 lea 0x2ef7(%rip),%rax 401119: 50 push %rax 40111a: 48 8b 05 b7 2e 00 00 mov 0x2eb7(%rip),%rax 401121: 5f pop %rdi 401122: 49 89 c2 mov %rax,%r10 401125: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40112c: 41 ff d2 call *%r10 40112f: 48 83 c4 00 add $0x0,%rsp 401133: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40113a: eb 07 jmp 401143 <главн+0x3d> 40113c: 48 c7 c0 00 00 00 00 mov $0x0,%rax 401143: 48 89 ec mov %rbp,%rsp 401146: 5d pop %rbp 401147: c3 ret
Дизассемблер GCC-RUSI
0000000000401040 <main>: 401040: 48 83 ec 08 sub $0x8,%rsp 401044: bf 04 20 40 00 mov $0x402004,%edi 401049: e8 e2 ff ff ff call 401030 <puts@plt> 40104e: 31 c0 xor %eax,%eax 401050: 48 83 c4 08 add $0x8,%rsp 401054: c3 ret
Что видно
Разница драматическая. Пройдёмся по пунктам.
1. Передача аргумента.
chibicc:
lea 0x2ef7(%rip),%rax push %rax ... pop %rdi
Адрес строки сначала кладётся в rax, потом пушится в стек, потом вытаскивается в rdi. Три инструкции вместо одной.
GCC:
mov $0x402004,%edi
Адрес строки сразу попадает в edi (младшие 32 бита rdi). Одна инструкция.
2. Вызов функции.
chibicc:
mov 0x2eb7(%rip),%rax mov %rax,%r10 mov $0x0,%rax call *%r10
Адрес printf загружается из GOT в регистр, потом перекладывается в r10, потом вызов через указатель. Ещё и rax обнуляется (для variadic-функций).
GCC:
call 401030 <puts@plt>
Прямой вызов puts через PLT. Одна инструкция.
3. printf против puts.
GCC заменил printf("Привет, мир!\n") на puts("Привет, мир!"). Это классическая оптимизация: если строка заканчивается на \n и нет форматирования, puts работает быстрее. chibicc не делает этого - вызывает printf напрямую.
4. Возврат значения.
chibicc:
mov $0x0,%rax jmp 401143 ... mov $0x0,%rax
Два mov $0x0,%rax и лишний jmp.
GCC:
xor %eax,%eax
Одна инструкция. xor регистра с самим собой - идиоматический способ обнуления, работает быстрее, чем mov.
5. Frame pointer.
chibicc:
push %rbp mov %rsp,%rbp ... pop %rbp
Сохраняет frame pointer, потому что chibicc не оптимизирует. GCC в -O2 выбрасывает его: sub $0x8,%rsp вместо push %rbp; mov %rsp,%rbp. Меньше инструкций, меньше стекового фрейма.
6. Лишние инструкции.
chibicc:
sub $0x10,%rsp mov %rsp,-0x8(%rbp) ... add $0x0,%rsp
Выделяет 16 байт стека, сохраняет указатель стека в память (зачем?), потом прибавляет 0 к rsp. Безсмысленные операции.
GCC:
sub $0x8,%rsp ... add $0x8,%rsp
Выделяет ровно столько, сколько нужно для выравнивания стека. Никаких лишних операций.
Итог
Что |
chibicc |
GCC |
|---|---|---|
Передача аргумента |
через стек (push/pop) |
прямо в регистр (mov … %edi) |
Вызов функции |
через указатель (call *%r10) |
напрямую (call puts@plt) |
printf vs puts |
printf |
puts (оптимизация) |
return 0 |
mov $0x0,%rax + jmp |
xor %eax,%eax |
Frame pointer |
есть (push %rbp) |
нет |
Лишние инструкции |
add $0x0,%rsp, mov %rsp,-0x8(%rbp) |
нет |
Размер кода |
~66 байт |
~21 байт |
Именно поэтому секция .text от GCC в 1.7 раза меньше. chibicc генерирует наивный код: каждая операция через стек, вызов через указатель, лишние jmp и mov. GCC оптимизирует: аргументы в регистрах, прямой вызов, puts вместо printf.
И самое главное: это тот же самый исходник. Один и тот же русский C. Разница только в компиляторе. В конце статьи под спойлером полные дизассемблерные тексты.
Простые числа до 100 000
Исходник (prost.c):
#включить <stdio.h> цел простые(цел н) { цел счёт = 0; для (цел и = 2; и <= н; и++) { цел флаг = 1; для (цел й = 2; й * й <= и; й++) { если (и % й == 0) { флаг = 0; прерви; } } если (флаг) счёт++; } возврат счёт; } цел главн(пусто) { printf("Простых до 100000: %d\n", простые(100000)); возврат 0; }
Тот же алгоритм на английском C для проверки, что ответ идентичен:
#include <stdio.h> int simple(int n) { int count = 0; for (int i = 2; i <= n; i++) { int flag = 1; for (int j = 2; j * j <= i; j++) { if (i % j == 0) { flag = 0; break; } } if (flag) count++; } return count; } int main(void) { printf("Простых до 100000: %d\n", simple(100000)); return 0; }
Собираем тремя способами:
./rusi.elf -o prost_chibicc prost.c /usr/local/gcc-rus-full/bin/gcc -O0 prost.c -o prost_gcc_O0 /usr/local/gcc-rus-full/bin/gcc -O2 prost.c -o prost_gcc_O2
Запускаем и проверяем, что ответ одинаковый:
$ ./prost_chibicc Простых до 100000: 9592 $ ./prost_gcc_O0 Простых до 100000: 9592 $ ./prost_gcc_O2 Простых до 100000: 9592
Все три дают одинаковый ответ.
Сравнение размеров:
$ stat -c '%n %s байт' prost_chibicc prost_gcc_O0 prost_gcc_O2 prost_chibicc 17872 байт prost_gcc_O0 15728 байт prost_gcc_O2 15728 байт
$ size prost_chibicc prost_gcc_O0 prost_gcc_O2 text data bss dec hex filename 2139 997 3 3139 c43 prost_chibicc 1125 544 8 1677 68d prost_gcc_O0 1106 544 8 1658 67a prost_gcc_O2
Замер скорости:
$ time ./prost_chibicc === chibicc === Простых до 100000: 9592 real 0m0,039s user 0m0,038s sys 0m0,002s $ time ./prost_gcc_O0 === gcc -O0 === Простых до 100000: 9592 real 0m0,016s user 0m0,012s sys 0m0,002s $ time ./prost_gcc_O2 === gcc -O2 === Простых до 100000: 9592 real 0m0,015s user 0m0,011s sys 0m0,004s
Итоговая таблица:
Метрика |
chibicc |
gcc -O0 |
gcc -O2 |
Разница (chibicc → gcc -O2) |
|---|---|---|---|---|
Размер файла |
17 872 байт |
15 728 байт |
15 728 байт |
−12% |
.text (код) |
2 139 байт |
1 125 байт |
1 106 байт |
−48% (почти в 2 раза!) |
.data |
997 байт |
544 байта |
544 байта |
−45% |
Итог (dec) |
3 139 |
1 677 |
1 658 |
−47% |
Время (real) |
0,039 с |
0,016 с |
0,015 с |
−62% (в 2,6 раза!) |
Время (user) |
0,038 с |
0,012 с |
0,011 с |
−71% (в 3,5 раза!) |
Ответ |
9592 |
9592 |
9592 |
одинаковый |
Почему так
GCC:
Держит переменные в регистрах, а не в стеке
Оптимизирует условие
й * й <= иРазматывает циклы
Инлайнит мелкие функции
Заменяет
printfнаputs, где возможно
chibicc:
Каждая операция через стек
Нет оптимизаций
Наивный код
Ассемблерные оптимизации работают.
РУСИ++: побочный продукт
Если перебирать компилятор, который парсит не только Си, а еще и Си++, то есть смысл сделать билингвальный построитель AST полностью. Были добавлены синонимы для всех слов.
Что это
RUSI++ - это C++ с русским синтаксисом. Работают:
Классы (
класс)Конструкторы
private/public(без перевода, оставлено как есть)Шаблоны (
шаблон<имя_типа T>)Наследование
Виртуальные функции
Пример
#включить <iostream> #включить <string> класс Приветствие { закрыт: std::string имя; открыт: Приветствие(конст std::string& н) : имя(н) {} пусто поздороваться() конст { std::cout << "Привет, " << имя << "!" << std::endl; } }; цел главн() { Приветствие п("мир"); п.поздороваться(); возврат 0; }
Сравнение с английским C++
#include <iostream> #include <string> class Greeting { private: std::string name; public: Greeting(const std::string& n) : name(n) {} void greet() const { std::cout << "Привет, " << name << "!" << std::endl; } }; int main() { Greeting g("мир"); g.greet(); return 0; }
Собран тот же код на английском C++ через тот же RUSI++:
/usr/local/gcc-rus-full/bin/g++ -O2 привет_класс.cpp -o привет_класс /usr/local/gcc-rus-full/bin/g++ -O2 privet_class_en.cpp -o privet_class_en
Проверка запуска:
$ ./привет_класс Привет, мир! $ ./privet_class_en Привет, мир!
Сравнение размеров:
$ stat -c '%n %s байт' привет_класс privet_class_en привет_класс 16672 байт privet_class_en 16664 байт
$ size привет_класс privet_class_en text data bss dec hex filename 2690 656 280 3626 e2a привет_класс 2690 656 280 3626 e2a privet_class_en
Сравнение кода:
$ objcopy -O binary --only-section=.text привет_класс /tmp/ru.bin $ objcopy -O binary --only-section=.text privet_class_en /tmp/en.bin $ cmp /tmp/ru.bin /tmp/en.bin && echo "✅ КОД ИДЕНТИЧЕН" || echo "❌ РАЗЛИЧАЕТСЯ" ✅ КОД ИДЕНТИЧЕН
Таблица:
Метрика |
привет_класс (рус) |
privet_class_en (англ) |
Разница |
|---|---|---|---|
Размер файла |
16 672 байт |
16 664 байта |
8 байт (0,05%) |
.text (код) |
2 690 байт |
2 690 байт |
0 |
.data |
656 байт |
656 байт |
0 |
.bss |
280 байт |
280 байт |
0 |
Машинный код |
идентичен |
идентичен |
0 |
Разница в 8 байт - это имена функций и классов в таблице символов (главн() vs main(), Приветствие vs Greeting). Сам код один и тот же.
Вывод
RUSI++ - это не переопределение слов через дефайны. Это полноценный C++ с русским синтаксисом. Классы, шаблоны, ООП - всё работает и компилируется в тот же машинный код, что и английский C++. Это побочный продукт работы над РУСИ: раз GCC поддерживает C++, а фронтенд русифицирован, C++ тоже стал русским.
Итог: форк chibicc породил три более совершенных языка
Что было: RUSI на chibicc - учебный компилятор для русского C.
Что стало:
Компилятор |
База |
Что умеет |
|---|---|---|
РУСИ (GCC) |
GCC 14.2 |
Русский C, оптимизации, все архитектуры |
РУСИ++ |
GCC 14.2 |
Русский C++, классы, шаблоны, ООП |
Объектный-РУСИ |
GCC 14.2 |
Русский Objective-C (не тестировался) |
Ключевое: все три - не «перевод ключевых слов», а полноценные фронтенды GCC с русским синтаксисом. После парсера AST идентичен английскому, дальше работает стандартный бэкенд GCC.
Перспективы применения
Куда можно применить технологию, с помощью которой создано почти всё? Преимуществом тут будет факт того, что Си все знают. Никого переучивать не нужно. Билингвальность же даёт обратную совместимость: всё, что написано ранее, можно без проблем применять. Да и переписывание такого компилятора на кириллическом Си - способ быстро прокачать инженерную школу.
Операционные системы
Linux - можно писать модули ядра
Windows - MinGW / Cygwin
macOS - через кросс-компиляцию
FreeBSD - нативная поддержка
Экзотические системы - всё, что поддерживает GCC
Встроенные системы
Прошивки для микроконтроллеров
Контроллеры (ARM Cortex-M, RISC-V)
Arduino (AVR)
Bare-metal
Процессоры
x86, x86-64
ARM, ARM64
RISC-V
MIPS
PowerPC
AVR
Всё, что поддерживает GCC
Отрасли
Приборостроение - уникальные приборы, измерительная техника
Робототехника - управление роботами
Системы связи - телекоммуникационное оборудование
Транспорт - встроенные системы автомобилей, поездов, самолётов
Образование
КуМир - школьный язык для обучения. RUSI может заменить его профессиональным инструментом с тем же русским синтаксисом, но с реальными возможностями GCC.
Экспорт в страны с кириллическим алфавитом
Болгария, Монголия, Сербия, Северная Македония, Казахстан, Кыргызстан - страны, где кириллица является официальной или широко используемой письменностью.
Создание отечественного стандарта ЯП Си
РУСИ может стать основой для отечественного стандарта языка системного программирования. Не «новый язык с нуля», а билингвальный стандарт:
Полная совместимость с международным стандартом C (ISO/IEC 9899)
Кириллический синтаксис как равноправный с латинским
Промышленная база GCC 14.2, а не учебный компилятор
Такой стандарт может быть принят для использования в … - везде, где требуется русскоязычная документация и код.
Появление нового стандарта раскладки.
Новая ru-раскладка с фигурными, квадратными и угловыми скобками однозначно продвинет применение русского языка в различных технологиях.
СПбГУ. RuC. Интерпретатор Терехова
До появления проекта RUSI в СПбГУ зародился свой Си с русскими словами - RuC. Виртуальная машина. Не сборщик в бинарь.
RuC - компилятор русского C в байт-код виртуальной машины. Автор - Андрей Терехов (СПбГУ). Проект остановился в 2023 году.
Почему остановился? Академический проект. Всё держалось на профессоре.
Названия похожи. Наверняка найдутся желающие столкнуть проекты по части именования. Оба могут сосуществовать со своими именами как Java и JavaScript.
Но есть идея даже концептуально развить RuC Терехова. И тут скорее win/win получится.
RuC написан на C++. RUSI++ - это C++ с русским синтаксисом. Значит:
Берём исходники RuC
Заменяем ключевые слова на русские (
class→класс,int→цел,return→возврат)Собираем через РУСИ++
Получаем тот же самый RuC, но с исходниками на русском
И возможно, в процессе появятся идеи развития проекта.
Заключение
Что сделано:
GCC 14.2.0 русифицирован
Тесты chibicc-RUSI проходят на 96.9% (два «провала» - баги chibicc, не RUSI)
RUSI-GCC быстрее и компактнее chibicc-RUSI в 2–3.5 раза
RUSI++ работает: классы, шаблоны, ООП
Что дальше:
Кросс-компиляция под ARM, RISC-V
Bare-metal поддержка (newlib, linker scripts)
Русификация стандартной библиотеки
Написание документации
Если кто размышлял о создании кириллического системного ЯП, то вот он - готовый, рабочий, всамделишный. Бонусом - инструкция по настройке раскладки, чтоб не переключать язык для скобок.
Ссылки
Программисты на Руси программируют на Си. RUSI: Концепт билингвального компилятора
Сфера - полностью кириллический язык программирования: от «Привет, мир» до HTTP-сервера и bare-metal
Бонус: фигурные скобки в русской раскладке
Проблема
Стандартная русская раскладка в Ubuntu 26 не имеет {, }, [, ], <, >. Клавиши, где они лежат в английской (Shift + [, Shift + ], Shift + ,, Shift + .), в русской заняты буквами х, ъ, б, ю.
Без фигурных скобок в C не написать ни функцию, ни блок, ни структуру. Без квадратных - не объявить массив или не обратиться к элементу. Без угловых - не подключить заголовок или не использовать шаблон. Переключать раскладку каждый раз - убивать поток.
Решение: задействуем правый Alt (AltGr). Он даёт третий уровень клавиатуры, специально созданный для ввода дополнительных символов. Он не конфликтует с Ctrl+X, Ctrl+C и другими системными сокращениями.
Что получится:
AltGr + х → { AltGr + ъ → } AltGr + щ → [ AltGr + з → ] AltGr + б → < AltGr + ю → > Левый Alt, оба Ctrl, Shift → работают как обычно
Почему именно щ и з для квадратных скобок: это самый простой способ. Можно, конечно, заморочиться и на правый Ctrl сделать комбинацию с кнопками «х» и «ъ» - путь сложный. Зато теперь конструкция вида если (щ[ы] < щ[ю]) { } не представляет никаких сложностей.
Патчим раскладку
Шаг 1. Резервная копия
sudo cp /usr/share/X11/xkb/symbols/ru /usr/share/X11/xkb/symbols/ru.orig
Шаг 2. Открыть файл раскладки
sudo nano /usr/share/X11/xkb/symbols/ru
Шаг 3. Найти блок winkeys
В самом начале файла:
// Windows layout default partial alphanumeric_keys xkb_symbols "winkeys" { include "ru(common)" name[Group1]= "Russian"; key <AE03> {[ 3, numerosign ]}; key <AE04> {[ 4, semicolon ]}; ... key <AB10> {[ period, comma ]}; key <BKSL> {[ backslash, slash ]}; };
Шаг 4. Заменить блок winkeys целиком
// Windows layout default partial alphanumeric_keys xkb_symbols "winkeys" { include "ru(common)" name[Group1]= "Russian"; key <AE03> {[ 3, numerosign ]}; key <AE04> {[ 4, semicolon ]}; key <AE05> {[ 5, percent ]}; key <AE06> {[ 6, colon ]}; key <AE07> {[ 7, question ]}; key <AE08> {[ 8, asterisk, U20BD ]}; // ruble key <AB10> {[ period, comma ]}; key <BKSL> {[ backslash, slash ]}; // --- добавлено для C-подобных языков --- key <AD11> { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_ha, Cyrillic_HA, braceleft, braceleft ] }; key <AD12> { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_hardsign, Cyrillic_HARDSIGN, braceright, braceright ] }; // --- квадратные скобки на AltGr: щ → [, з → ] --- key <AD09> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_shcha, Cyrillic_SHCHA, bracketleft, bracketleft ] }; key <AD10> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_ze, Cyrillic_ZE, bracketright, bracketright ] }; // --- угловые скобки на AltGr: б → <, ю → > --- key <AB08> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_be, Cyrillic_BE, less, less ] }; key <AB09> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_yu, Cyrillic_YU, greater, greater ] }; include "level3(ralt_switch)" };
Пояснения:
<AD11>- физическая клавиша[, в русской раскладкех<AD12>- физическая клавиша], в русской раскладкеъ<AD09>- физическая клавишаO, в русской раскладкещ<AD10>- физическая клавишаP, в русской раскладкез<AB08>- физическая клавиша,, в русской раскладкеб<AB09>- физическая клавиша., в русской раскладкеюFOUR_LEVEL- четыре уровня: без модификатора, Shift, AltGr, Shift+AltGrbraceleft/braceright-{и}bracketleft/bracketright-[и]less/greater-<и>level3(ralt_switch)- включает правый Alt как AltGr
Шаг 5. Перезагрузить систему
sudo reboot
Шаг 6. Проверить
Открыть любой текстовый редактор:
х → х, Shift + х → Х, AltGr + х → { ъ → ъ, Shift + ъ → Ъ, AltGr + ъ → } щ → щ, Shift + щ → Щ, AltGr + щ → [ з → з, Shift + з → З, AltGr + з → ] б → б, Shift + б → Б, AltGr + б → < ю → ю, Shift + ю → Ю, AltGr + ю → >
Если AltGr + х даёт { - всё готово.
Кастомная XKB-раскладка работает на уровне системы, без конфликтов. Левый Alt, оба Ctrl, Shift - как обычно.
Спойлеры
Ниже приведены спойлеры для тех, кто хочет вникнуть в детали.
? Git diff
[diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index aae998d0f73..6c12d22fc17 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -383,245 +383,465 @@ static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); reserved word too, but only if it follows an '@' sign. */ const struct c_common_resword c_common_reswords[] = -{ +{ { "_Alignas", RID_ALIGNAS, D_CONLY }, + { "_Выравнивание", RID_ALIGNAS, D_CONLY }, { "_Alignof", RID_ALIGNOF, D_CONLY }, + { "_Выравнивание_типа", RID_ALIGNOF, D_CONLY }, { "_Atomic", RID_ATOMIC, D_CONLY }, + { "_Атом", RID_ATOMIC, D_CONLY }, { "_BitInt", RID_BITINT, D_CONLY }, + { "_бит_цел", RID_BITINT, D_CONLY }, { "_Bool", RID_BOOL, D_CONLY }, + { "_лог", RID_BOOL, D_CONLY }, { "_Complex", RID_COMPLEX, 0 }, + { "_комплекс", RID_COMPLEX, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, + { "_мнимое", RID_IMAGINARY, D_CONLY }, { "_Float16", RID_FLOAT16, 0 }, + { "_вещ16", RID_FLOAT16, 0 }, { "_Float32", RID_FLOAT32, 0 }, + { "_вещ32", RID_FLOAT32, 0 }, { "_Float64", RID_FLOAT64, 0 }, + { "_вещ64", RID_FLOAT64, 0 }, { "_Float128", RID_FLOAT128, 0 }, + { "_вещ128", RID_FLOAT128, 0 }, { "_Float32x", RID_FLOAT32X, 0 }, + { "_вещ32x", RID_FLOAT32X, 0 }, { "_Float64x", RID_FLOAT64X, 0 }, + { "_вещ64x", RID_FLOAT64X, 0 }, { "_Float128x", RID_FLOAT128X, 0 }, + { "_вещ128x", RID_FLOAT128X, 0 }, { "_Decimal32", RID_DFLOAT32, D_CONLY }, + { "_десят32", RID_DFLOAT32, D_CONLY }, { "_Decimal64", RID_DFLOAT64, D_CONLY }, + { "_десят64", RID_DFLOAT64, D_CONLY }, { "_Decimal128", RID_DFLOAT128, D_CONLY }, + { "_десят128", RID_DFLOAT128, D_CONLY }, { "_Fract", RID_FRACT, D_CONLY | D_EXT }, + { "_дробь", RID_FRACT, D_CONLY | D_EXT }, { "_Accum", RID_ACCUM, D_CONLY | D_EXT }, + { "_аккум", RID_ACCUM, D_CONLY | D_EXT }, { "_Sat", RID_SAT, D_CONLY | D_EXT }, + { "_насыщ", RID_SAT, D_CONLY | D_EXT }, { "_Static_assert", RID_STATIC_ASSERT, D_CONLY }, + { "_стат_проверка", RID_STATIC_ASSERT, D_CONLY }, { "_Noreturn", RID_NORETURN, D_CONLY }, + { "_Безвозврат", RID_NORETURN, D_CONLY }, { "_Generic", RID_GENERIC, D_CONLY }, + { "_Обобщ", RID_GENERIC, D_CONLY }, { "_Thread_local", RID_THREAD, D_CONLY }, + { "_Поток_лок", RID_THREAD, D_CONLY }, { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, + { "__ФУНКЦИЯ__", RID_FUNCTION_NAME, 0 }, { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, + { "__КРАСИВАЯ_ФУНКЦИЯ__", RID_PRETTY_FUNCTION_NAME, 0 }, { "__alignof", RID_ALIGNOF, 0 }, + { "__выравн_от", RID_ALIGNOF, 0 }, { "__alignof__", RID_ALIGNOF, 0 }, + { "__выравн_от__", RID_ALIGNOF, 0 }, { "__asm", RID_ASM, 0 }, + { "__ассемблер", RID_ASM, 0 }, { "__asm__", RID_ASM, 0 }, + { "__ассемблер__", RID_ASM, 0 }, { "__attribute", RID_ATTRIBUTE, 0 }, + { "__атрибут", RID_ATTRIBUTE, 0 }, { "__attribute__", RID_ATTRIBUTE, 0 }, + { "__атрибут__", RID_ATTRIBUTE, 0 }, { "__auto_type", RID_AUTO_TYPE, D_CONLY }, + { "__авто_тип", RID_AUTO_TYPE, D_CONLY }, { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY }, + { "__встр_адрес_от", RID_ADDRESSOF, D_CXXONLY }, { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, + { "__встр_барьер_ассоц", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY }, + { "__встр_бит_преобр", RID_BUILTIN_BIT_CAST, D_CXXONLY }, { "__builtin_call_with_static_chain", RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, + { "__встр_вызов_со_стат_цепью", + RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY }, + { "__встр_выбор_выраж", RID_CHOOSE_EXPR, D_CONLY }, { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY }, + { "__встр_комплекс", RID_BUILTIN_COMPLEX, D_CONLY }, { "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 }, + { "__встр_преобр_вектор", RID_BUILTIN_CONVERTVECTOR, 0 }, { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, + { "__встр_имеет_атрибут", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, + { "__встр_очистка", RID_BUILTIN_LAUNDER, D_CXXONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, + { "__встр_перемешать", RID_BUILTIN_SHUFFLE, 0 }, { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, + { "__встр_перемешать_вектор", RID_BUILTIN_SHUFFLEVECTOR, 0 }, { "__builtin_stdc_bit_ceil", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_бит_потолок", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_bit_floor", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_бит_пол", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_bit_width", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_бит_ширина", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_count_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_считать_единицы", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_count_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_считать_нули", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_leading_one", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_ведущий_один", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_leading_zero", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_ведущий_нуль", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_trailing_one", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_хвостовой_один", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_trailing_zero", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_хвостовой_нуль", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_has_single_bit", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_имеет_один_бит", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_ведущие_единицы", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_ведущие_нули", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_хвостовые_единицы", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_хвостовые_нули", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, + { "__встр_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, + { "__встр_смещение", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, + { "__встр_типы_совместимы", RID_TYPES_COMPATIBLE_P, D_CONLY }, { "__builtin_va_arg", RID_VA_ARG, 0 }, + { "__встр_va_arg", RID_VA_ARG, 0 }, { "__complex", RID_COMPLEX, 0 }, + { "__комплекс", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 }, + { "__комплекс__", RID_COMPLEX, 0 }, { "__const", RID_CONST, 0 }, + { "конст", RID_CONST, 0 }, { "__const__", RID_CONST, 0 }, + { "__неизм__", RID_CONST, 0 }, { "__constinit", RID_CONSTINIT, D_CXXONLY }, + { "__конст_иниц", RID_CONSTINIT, D_CXXONLY }, { "__decltype", RID_DECLTYPE, D_CXXONLY }, + { "__тип_выраж", RID_DECLTYPE, D_CXXONLY }, { "__extension__", RID_EXTENSION, 0 }, + { "__расширение__", RID_EXTENSION, 0 }, { "__func__", RID_C99_FUNCTION_NAME, 0 }, + { "__функ__", RID_C99_FUNCTION_NAME, 0 }, { "__imag", RID_IMAGPART, 0 }, + { "__мнимая", RID_IMAGPART, 0 }, { "__imag__", RID_IMAGPART, 0 }, + { "__мнимая__", RID_IMAGPART, 0 }, { "__inline", RID_INLINE, 0 }, + { "__встр", RID_INLINE, 0 }, { "__inline__", RID_INLINE, 0 }, + { "__встр__", RID_INLINE, 0 }, { "__label__", RID_LABEL, 0 }, + { "__метка__", RID_LABEL, 0 }, { "__null", RID_NULL, 0 }, + { "__нуль", RID_NULL, 0 }, { "__real", RID_REALPART, 0 }, + { "__действ", RID_REALPART, 0 }, { "__real__", RID_REALPART, 0 }, + { "__действ__", RID_REALPART, 0 }, { "__restrict", RID_RESTRICT, 0 }, + { "__огран", RID_RESTRICT, 0 }, { "__restrict__", RID_RESTRICT, 0 }, + { "__огран__", RID_RESTRICT, 0 }, { "__signed", RID_SIGNED, 0 }, + { "__знак", RID_SIGNED, 0 }, { "__signed__", RID_SIGNED, 0 }, + { "__знак__", RID_SIGNED, 0 }, { "__thread", RID_THREAD, 0 }, + { "__поток", RID_THREAD, 0 }, { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 }, + { "__транзакция_атомарн", RID_TRANSACTION_ATOMIC, 0 }, { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 }, + { "__транзакция_расслабл", RID_TRANSACTION_RELAXED, 0 }, { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 }, + { "__транзакция_отмена", RID_TRANSACTION_CANCEL, 0 }, { "__typeof", RID_TYPEOF, 0 }, + { "__тип_от", RID_TYPEOF, 0 }, { "__typeof__", RID_TYPEOF, 0 }, + { "__тип_от__", RID_TYPEOF, 0 }, { "__typeof_unqual", RID_TYPEOF_UNQUAL, D_CONLY }, + { "__тип_от_без_квал", RID_TYPEOF_UNQUAL, D_CONLY }, { "__typeof_unqual__", RID_TYPEOF_UNQUAL, D_CONLY }, + { "__тип_от_без_квал__", RID_TYPEOF_UNQUAL, D_CONLY }, { "__volatile", RID_VOLATILE, 0 }, + { "__неуст", RID_VOLATILE, 0 }, { "__volatile__", RID_VOLATILE, 0 }, + { "__неуст__", RID_VOLATILE, 0 }, { "__GIMPLE", RID_GIMPLE, D_CONLY }, - { "__PHI", RID_PHI, D_CONLY }, + { "__PHI", RID_PHI, D_CONLY }, // { "__RTL", RID_RTL, D_CONLY }, { "alignas", RID_ALIGNAS, D_C23 | D_CXX11 | D_CXXWARN }, + { "выравн_как", RID_ALIGNAS, D_C23 | D_CXX11 | D_CXXWARN }, { "alignof", RID_ALIGNOF, D_C23 | D_CXX11 | D_CXXWARN }, + { "выравн_от", RID_ALIGNOF, D_C23 | D_CXX11 | D_CXXWARN }, { "asm", RID_ASM, D_ASM }, + { "асм", RID_ASM, D_ASM }, { "auto", RID_AUTO, 0 }, + { "авто", RID_AUTO, 0 }, { "bool", RID_BOOL, D_C23 | D_CXXWARN }, + //{ "бул", RID_BOOL, D_C23 | D_CXXWARN }, + { "бул", RID_BOOL, 0 }, { "break", RID_BREAK, 0 }, + { "прерви", RID_BREAK, 0 }, { "case", RID_CASE, 0 }, + { "случай", RID_CASE, 0 }, { "catch", RID_CATCH, D_CXX_OBJC | D_CXXWARN }, + { "поймать", RID_CATCH, D_CXX_OBJC | D_CXXWARN }, { "char", RID_CHAR, 0 }, + { "символ", RID_CHAR, 0 }, { "char8_t", RID_CHAR8, D_CXX_CHAR8_T_FLAGS | D_CXXWARN }, + { "симв8_t", RID_CHAR8, D_CXX_CHAR8_T_FLAGS | D_CXXWARN }, { "char16_t", RID_CHAR16, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "симв16_t", RID_CHAR16, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "char32_t", RID_CHAR32, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "симв32_t", RID_CHAR32, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN }, + { "класс", RID_CLASS, D_CXX_OBJC | D_CXXWARN }, + { "__конст", RID_CONST, 0 }, { "consteval", RID_CONSTEVAL, D_CXXONLY | D_CXX20 | D_CXXWARN }, + { "конст_вычисл", RID_CONSTEVAL, D_CXXONLY | D_CXX20 | D_CXXWARN }, { "constexpr", RID_CONSTEXPR, D_C23 | D_CXX11 | D_CXXWARN }, + { "конст_выраж", RID_CONSTEXPR, D_C23 | D_CXX11 | D_CXXWARN }, { "constinit", RID_CONSTINIT, D_CXXONLY | D_CXX20 | D_CXXWARN }, + { "конст_иниц", RID_CONSTINIT, D_CXXONLY | D_CXX20 | D_CXXWARN }, { "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN }, + { "конст_преобр", RID_CONSTCAST, D_CXXONLY | D_CXXWARN }, { "continue", RID_CONTINUE, 0 }, + { "продолжи", RID_CONTINUE, 0 }, { "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "тип_выраж", RID_DECLTYPE, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "default", RID_DEFAULT, 0 }, + { "умолч", RID_DEFAULT, 0 }, { "delete", RID_DELETE, D_CXXONLY | D_CXXWARN }, + { "удалить", RID_DELETE, D_CXXONLY | D_CXXWARN }, { "do", RID_DO, 0 }, + { "делай", RID_DO, 0 }, { "double", RID_DOUBLE, 0 }, + { "двойн", RID_DOUBLE, 0 }, { "dynamic_cast", RID_DYNCAST, D_CXXONLY | D_CXXWARN }, + { "динам_преобр", RID_DYNCAST, D_CXXONLY | D_CXXWARN }, { "else", RID_ELSE, 0 }, + { "иначе", RID_ELSE, 0 }, { "enum", RID_ENUM, 0 }, + { "переч", RID_ENUM, 0 }, { "explicit", RID_EXPLICIT, D_CXXONLY | D_CXXWARN }, + { "явный", RID_EXPLICIT, D_CXXONLY | D_CXXWARN }, { "export", RID_EXPORT, D_CXXONLY | D_CXXWARN }, + { "экспорт", RID_EXPORT, D_CXXONLY | D_CXXWARN }, { "extern", RID_EXTERN, 0 }, + { "внеш", RID_EXTERN, 0 }, { "false", RID_FALSE, D_C23 | D_CXXWARN }, + { "ложь", RID_FALSE, 0 }, { "float", RID_FLOAT, 0 }, + { "плав", RID_FLOAT, 0 }, { "for", RID_FOR, 0 }, + { "для", RID_FOR, 0 }, { "friend", RID_FRIEND, D_CXXONLY | D_CXXWARN }, + { "друг", RID_FRIEND, D_CXXONLY | D_CXXWARN }, { "goto", RID_GOTO, 0 }, + { "перейти", RID_GOTO, 0 }, { "if", RID_IF, 0 }, + { "если", RID_IF, 0 }, { "inline", RID_INLINE, D_EXT89 }, + { "инлайн", RID_INLINE, D_EXT89 }, { "int", RID_INT, 0 }, + { "цел", RID_INT_RU, 0 }, { "long", RID_LONG, 0 }, + { "длин", RID_LONG, 0 }, { "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN }, + { "измен", RID_MUTABLE, D_CXXONLY | D_CXXWARN }, { "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN }, + { "пространство", RID_NAMESPACE, D_CXXONLY | D_CXXWARN }, { "new", RID_NEW, D_CXXONLY | D_CXXWARN }, + { "новый", RID_NEW, D_CXXONLY | D_CXXWARN }, { "noexcept", RID_NOEXCEPT, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "без_искл", RID_NOEXCEPT, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "nullptr", RID_NULLPTR, D_C23 | D_CXX11 | D_CXXWARN }, + { "пуст_указ", RID_NULLPTR, D_C23 | D_CXX11 | D_CXXWARN }, { "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN }, + { "оператор", RID_OPERATOR, D_CXXONLY | D_CXXWARN }, { "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN }, + { "закрыт", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN }, { "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN }, + { "защищ", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN }, { "public", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN }, + { "открыт", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN }, { "register", RID_REGISTER, 0 }, + { "регистр", RID_REGISTER, 0 }, { "reinterpret_cast", RID_REINTCAST, D_CXXONLY | D_CXXWARN }, + { "переинт_преобр", RID_REINTCAST, D_CXXONLY | D_CXXWARN }, { "restrict", RID_RESTRICT, D_CONLY | D_C99 }, + { "огранич", RID_RESTRICT, D_CONLY | D_C99 }, { "return", RID_RETURN, 0 }, + { "возврат", RID_RETURN, 0 }, { "short", RID_SHORT, 0 }, + { "корот", RID_SHORT, 0 }, { "signed", RID_SIGNED, 0 }, + { "знак", RID_SIGNED, 0 }, { "sizeof", RID_SIZEOF, 0 }, + { "размер", RID_SIZEOF, 0 }, { "static", RID_STATIC, 0 }, + { "стат", RID_STATIC, 0 }, { "static_assert", RID_STATIC_ASSERT, D_C23 | D_CXX11 | D_CXXWARN }, + { "стат_проверка", RID_STATIC_ASSERT, D_C23 | D_CXX11 | D_CXXWARN }, { "static_cast", RID_STATCAST, D_CXXONLY | D_CXXWARN }, + { "стат_преобр", RID_STATCAST, D_CXXONLY | D_CXXWARN }, { "struct", RID_STRUCT, 0 }, + { "структ", RID_STRUCT, 0 }, { "switch", RID_SWITCH, 0 }, + { "выбор", RID_SWITCH, 0 }, { "template", RID_TEMPLATE, D_CXXONLY | D_CXXWARN }, + { "шаблон", RID_TEMPLATE, D_CXXONLY | D_CXXWARN }, { "this", RID_THIS, D_CXXONLY | D_CXXWARN }, + { "этот", RID_THIS, D_CXXONLY | D_CXXWARN }, { "thread_local", RID_THREAD, D_C23 | D_CXX11 | D_CXXWARN }, + { "_Поток_лок", RID_THREAD, D_C23 | D_CXX11 | D_CXXWARN }, { "throw", RID_THROW, D_CXX_OBJC | D_CXXWARN }, + { "бросить", RID_THROW, D_CXX_OBJC | D_CXXWARN }, { "true", RID_TRUE, D_C23 | D_CXXWARN }, + { "истина", RID_TRUE, 0 }, { "try", RID_TRY, D_CXX_OBJC | D_CXXWARN }, + { "попытка", RID_TRY, D_CXX_OBJC | D_CXXWARN }, { "typedef", RID_TYPEDEF, 0 }, + { "типдеф", RID_TYPEDEF, 0 }, { "typename", RID_TYPENAME, D_CXXONLY | D_CXXWARN }, + { "имя_типа", RID_TYPENAME, D_CXXONLY | D_CXXWARN }, { "typeid", RID_TYPEID, D_CXXONLY | D_CXXWARN }, + { "ид_типа", RID_TYPEID, D_CXXONLY | D_CXXWARN }, { "typeof", RID_TYPEOF, D_EXT11 }, + { "типоф", RID_TYPEOF, D_EXT11 }, { "typeof_unqual", RID_TYPEOF_UNQUAL, D_CONLY | D_C23 }, + { "тип_от_без_квал", RID_TYPEOF_UNQUAL, D_CONLY | D_C23 }, { "union", RID_UNION, 0 }, + { "объед", RID_UNION, 0 }, { "unsigned", RID_UNSIGNED, 0 }, + { "беззнак", RID_UNSIGNED, 0 }, { "using", RID_USING, D_CXXONLY | D_CXXWARN }, + { "используя", RID_USING, D_CXXONLY | D_CXXWARN }, { "virtual", RID_VIRTUAL, D_CXXONLY | D_CXXWARN }, + { "вирт", RID_VIRTUAL, D_CXXONLY | D_CXXWARN }, { "void", RID_VOID, 0 }, + { "пусто", RID_VOID, 0 }, { "volatile", RID_VOLATILE, 0 }, + { "летуч", RID_VOLATILE, 0 }, { "wchar_t", RID_WCHAR, D_CXXONLY }, + { "ш_симв", RID_WCHAR, D_CXXONLY }, { "while", RID_WHILE, 0 }, + { "пока", RID_WHILE, 0 }, /* C++ transactional memory. */ { "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, + { "синхрон", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, { "atomic_noexcept", RID_ATOMIC_NOEXCEPT, D_CXXONLY | D_TRANSMEM }, + { "атомарн_без_искл", RID_ATOMIC_NOEXCEPT, D_CXXONLY | D_TRANSMEM }, { "atomic_cancel", RID_ATOMIC_CANCEL, D_CXXONLY | D_TRANSMEM }, + { "атомарн_отмена", RID_ATOMIC_CANCEL, D_CXXONLY | D_TRANSMEM }, { "atomic_commit", RID_TRANSACTION_ATOMIC, D_CXXONLY | D_TRANSMEM }, + { "атомарн_фиксация", RID_TRANSACTION_ATOMIC, D_CXXONLY | D_TRANSMEM }, /* Concepts-related keywords */ { "concept", RID_CONCEPT, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, + { "концепт", RID_CONCEPT, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, { "requires", RID_REQUIRES, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, + { "требует", RID_REQUIRES, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, /* Modules-related keywords, these are internal unspellable tokens, created by the preprocessor. */ { "module ", RID__MODULE, D_CXX_MODULES_FLAGS | D_CXXWARN }, + { "модуль ", RID__MODULE, D_CXX_MODULES_FLAGS | D_CXXWARN }, { "import ", RID__IMPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, + { "импорт ", RID__IMPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, { "export ", RID__EXPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, + { "экспорт ", RID__EXPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, /* Coroutines-related keywords */ { "co_await", RID_CO_AWAIT, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, + { "со_ждать", RID_CO_AWAIT, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, { "co_yield", RID_CO_YIELD, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, + { "со_уступить", RID_CO_YIELD, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, { "co_return", RID_CO_RETURN, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, + { "со_возврат", RID_CO_RETURN, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, /* These Objective-C keywords are recognized only immediately after an '@'. */ { "compatibility_alias", RID_AT_ALIAS, D_OBJC }, + { "совместим_псевдоним", RID_AT_ALIAS, D_OBJC }, { "defs", RID_AT_DEFS, D_OBJC }, + { "описания", RID_AT_DEFS, D_OBJC }, { "encode", RID_AT_ENCODE, D_OBJC }, + { "кодировать", RID_AT_ENCODE, D_OBJC }, { "end", RID_AT_END, D_OBJC }, + { "конец", RID_AT_END, D_OBJC }, { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, + { "реализация", RID_AT_IMPLEMENTATION, D_OBJC }, { "interface", RID_AT_INTERFACE, D_OBJC }, + { "интерфейс", RID_AT_INTERFACE, D_OBJC }, { "protocol", RID_AT_PROTOCOL, D_OBJC }, + { "протокол", RID_AT_PROTOCOL, D_OBJC }, { "selector", RID_AT_SELECTOR, D_OBJC }, + { "селектор", RID_AT_SELECTOR, D_OBJC }, { "finally", RID_AT_FINALLY, D_OBJC }, + { "наконец", RID_AT_FINALLY, D_OBJC }, { "optional", RID_AT_OPTIONAL, D_OBJC }, + { "необязат", RID_AT_OPTIONAL, D_OBJC }, { "required", RID_AT_REQUIRED, D_OBJC }, + { "обязат", RID_AT_REQUIRED, D_OBJC }, { "property", RID_AT_PROPERTY, D_OBJC }, + { "свойство", RID_AT_PROPERTY, D_OBJC }, { "package", RID_AT_PACKAGE, D_OBJC }, + { "пакет", RID_AT_PACKAGE, D_OBJC }, { "synthesize", RID_AT_SYNTHESIZE, D_OBJC }, + { "синтез", RID_AT_SYNTHESIZE, D_OBJC }, { "dynamic", RID_AT_DYNAMIC, D_OBJC }, + { "динам", RID_AT_DYNAMIC, D_OBJC }, /* These are recognized only in protocol-qualifier context (see above) */ { "bycopy", RID_BYCOPY, D_OBJC }, + { "копировать", RID_BYCOPY, D_OBJC }, { "byref", RID_BYREF, D_OBJC }, + { "по_ссылке", RID_BYREF, D_OBJC }, { "in", RID_IN, D_OBJC }, + { "вход", RID_IN, D_OBJC }, { "inout", RID_INOUT, D_OBJC }, + { "вход_выход", RID_INOUT, D_OBJC }, { "oneway", RID_ONEWAY, D_OBJC }, + { "однонапр", RID_ONEWAY, D_OBJC }, { "out", RID_OUT, D_OBJC }, + { "выход", RID_OUT, D_OBJC }, /* These are recognized inside a property attribute list */ { "assign", RID_ASSIGN, D_OBJC }, + { "присвоить", RID_ASSIGN, D_OBJC }, { "atomic", RID_PROPATOMIC, D_OBJC }, + { "атомарн", RID_PROPATOMIC, D_OBJC }, { "copy", RID_COPY, D_OBJC }, + { "копия", RID_COPY, D_OBJC }, { "getter", RID_GETTER, D_OBJC }, + { "получатель", RID_GETTER, D_OBJC }, { "nonatomic", RID_NONATOMIC, D_OBJC }, + { "не_атомарн", RID_NONATOMIC, D_OBJC }, { "readonly", RID_READONLY, D_OBJC }, + { "только_чтение", RID_READONLY, D_OBJC }, { "readwrite", RID_READWRITE, D_OBJC }, + { "чтение_запись", RID_READWRITE, D_OBJC }, { "retain", RID_RETAIN, D_OBJC }, + { "удержать", RID_RETAIN, D_OBJC }, { "setter", RID_SETTER, D_OBJC }, + { "установщик", RID_SETTER, D_OBJC }, /* These are Objective C implementation of nullability, accepted only in specific contexts. */ { "null_unspecified", RID_NULL_UNSPECIFIED, D_OBJC }, + { "нуль_не_указан", RID_NULL_UNSPECIFIED, D_OBJC }, { "nullable", RID_NULLABLE, D_OBJC }, + { "может_быть_нуль", RID_NULLABLE, D_OBJC }, { "nonnull", RID_NONNULL, D_OBJC }, + { "не_нуль", RID_NONNULL, D_OBJC }, { "null_resettable", RID_NULL_RESETTABLE, D_OBJC }, + { "нуль_сбрасываемый",RID_NULL_RESETTABLE, D_OBJC }, }; const unsigned int num_c_common_reswords = ARRAY_SIZE (c_common_reswords); @@ -4792,6 +5012,7 @@ c_common_nodes_and_builtins (void) c_define_builtins (va_list_ref_type_node, va_list_arg_type_node); main_identifier_node = get_identifier ("main"); + main_ru_identifier_node = get_identifier ("главн"); /* Create the built-in __null node. It is important that this is not shared. */ @@ -8802,6 +9023,7 @@ keyword_begins_type_specifier (enum rid keyword) { case RID_AUTO_TYPE: case RID_INT: + case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -8847,6 +9069,7 @@ keyword_is_type_qualifier (enum rid keyword) switch (keyword) { case RID_CONST: + //case RID_CONST_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_VOLATILE: case RID_RESTRICT: case RID_ATOMIC: diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 2d5f5399885..d94ebf3fe89 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -260,7 +260,11 @@ enum rid RID_FIRST_PQ = RID_IN, RID_LAST_PQ = RID_ONEWAY, RID_FIRST_PATTR = RID_GETTER, - RID_LAST_PATTR = RID_NULL_RESETTABLE + RID_LAST_PATTR = RID_NULL_RESETTABLE, + + RID_INT_RU, + RID_CONST_RU, + RID_MAIN_RU }; #define OBJC_IS_AT_KEYWORD(rid) \ diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 0e52f217618..cbb738b142b 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -10502,6 +10502,14 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, &attributes, &expr, NULL, DEPRECATED_NORMAL); invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1); + /* === ДОБАВЛЕНО: замена "главн" на "main" === */ + if (decl1 != NULL_TREE && TREE_CODE (decl1) == FUNCTION_DECL) + { + if (DECL_NAME (decl1) == main_ru_identifier_node) + DECL_NAME (decl1) = main_identifier_node; + } + /* === КОНЕЦ ДОБАВЛЕННОГО БЛОКА === */ + /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == NULL_TREE @@ -12466,6 +12474,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, } return specs; case RID_INT: + case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! if (specs->saturating_p) error_at (loc, ("both %<_Sat%> and %<int%> in " diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 5fcfff7134a..1e1a68eb1b8 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -588,6 +588,7 @@ c_keyword_starts_typename (enum rid keyword) case RID_SIGNED: case RID_COMPLEX: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -792,6 +793,7 @@ c_token_starts_declspecs (c_token *token) case RID_SIGNED: case RID_COMPLEX: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -3446,6 +3448,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, case RID_SIGNED: case RID_COMPLEX: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -5173,6 +5176,7 @@ c_parser_gnu_attribute_any_word (c_parser *parser) case RID_COMPLEX: case RID_THREAD: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -13901,6 +13905,7 @@ c_parser_objc_selector (c_parser *parser) case RID_BYREF: case RID_ONEWAY: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc index 1110db7f8d0..d29f5c20100 100644 --- a/gcc/cp/lex.cc +++ b/gcc/cp/lex.cc @@ -262,17 +262,33 @@ init_reswords (void) /* The Objective-C keywords are all context-dependent. */ mask |= D_OBJC; - ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX); - for (i = 0; i < num_c_common_reswords; i++) - { - if (c_common_reswords[i].disable & D_CONLY) - continue; - id = get_identifier (c_common_reswords[i].word); - C_SET_RID_CODE (id, c_common_reswords[i].rid); - ridpointers [(int) c_common_reswords[i].rid] = id; - if (! (c_common_reswords[i].disable & mask)) - set_identifier_kind (id, cik_keyword); - } +// В gcc/cp/lex.cc (или gcc/c-family/c-common.cc для C) +// Добавить специальную обработку после основного цикла + +ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX); +for (i = 0; i < num_c_common_reswords; i++) +{ + if (c_common_reswords[i].disable & D_CONLY) + continue; + id = get_identifier (c_common_reswords[i].word); + C_SET_RID_CODE (id, c_common_reswords[i].rid); + ridpointers [(int) c_common_reswords[i].rid] = id; + if (! (c_common_reswords[i].disable & mask)) + set_identifier_kind (id, cik_keyword); +} + +// ✅ ДОБАВИТЬ: сделать RID_INT_RU и RID_INT эквивалентными +// Делаем так, чтобы оба ключевых слова указывали на ОДИН идентификатор +if (ridpointers[RID_INT] && ridpointers[RID_INT_RU]) +{ + // Вариант 1: переиспользовать идентификатор RID_INT для RID_INT_RU + ridpointers[RID_INT_RU] = ridpointers[RID_INT]; + + // ИЛИ вариант 2: сделать оба указателя на идентификатор "цел" + // ridpointers[RID_INT] = ridpointers[RID_INT_RU]; +} + + for (i = 0; i < NUM_INT_N_ENTS; i++) { diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 9fa74342919..a5be6ec6955 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -754,6 +754,7 @@ enum tree_index { TI_VOID_LIST_NODE, TI_MAIN_IDENTIFIER, + TI_MAIN_RU_IDENTIFIER, TI_SAT_SFRACT_TYPE, TI_SAT_FRACT_TYPE, diff --git a/gcc/tree.h b/gcc/tree.h index ee2aae332a4..b3336250935 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4606,9 +4606,11 @@ tree_strip_any_location_wrapper (tree exp) #define void_list_node global_trees[TI_VOID_LIST_NODE] #define main_identifier_node global_trees[TI_MAIN_IDENTIFIER] +#define main_ru_identifier_node global_trees[TI_MAIN_RU_IDENTIFIER] #define MAIN_NAME_P(NODE) \ (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node) - +#define MAIN_RU_NAME_P(NODE) \ + (IDENTIFIER_NODE_CHECK (NODE) == main_ru_identifier_node) // ← ДОБАВИТЬ /* Optimization options (OPTIMIZATION_NODE) to use for default and current functions. */ #define optimization_default_node global_trees[TI_OPTIMIZATION_DEFAULT] diff --git a/libcpp/directives.cc b/libcpp/directives.cc index 479f8c716e8..aed62174ab0 100644 --- a/libcpp/directives.cc +++ b/libcpp/directives.cc @@ -190,6 +190,23 @@ enum static const directive dtable[] = { DIRECTIVE_TABLE + + /* Русские синонимы для директив */ + { do_define, UC"определить", sizeof "определить" - 1, KANDR, IN_I }, + { do_include, UC"включить", sizeof "включить" - 1, KANDR, INCL | EXPAND }, + { do_if, UC"если", sizeof "если" - 1, KANDR, COND | IF_COND | EXPAND }, + { do_ifdef, UC"еслиопр", sizeof "еслиопр" - 1, KANDR, COND | IF_COND }, + { do_ifndef, UC"еслинеопр", sizeof "еслинеопр" - 1, KANDR, COND | IF_COND }, + { do_elif, UC"иначеесли", sizeof "иначеесли" - 1, STDC89, COND | EXPAND }, + { do_else, UC"иначе", sizeof "иначе" - 1, KANDR, COND }, + { do_endif, UC"конецесли", sizeof "конецесли" - 1, KANDR, COND }, + { do_undef, UC"отменить", sizeof "отменить" - 1, KANDR, IN_I }, + { do_error, UC"ошибка", sizeof "ошибка" - 1, STDC89, 0 }, + { do_warning, UC"предупреждение", sizeof "предупреждение" - 1, STDC23, 0 }, + { do_pragma, UC"прагма", sizeof "прагма" - 1, STDC89, IN_I }, + { do_line, UC"строка", sizeof "строка" - 1, KANDR, EXPAND }, + { do_include_next, UC"включить_след", sizeof "включить_след" - 1, EXTENSION, INCL | EXPAND }, + { do_import, UC"импорт", sizeof "импорт" - 1, EXTENSION, INCL | EXPAND }, }; #undef D @@ -197,7 +214,25 @@ DIRECTIVE_TABLE when suggesting corrections for misspelled directives. */ #define D(name, t, origin, flags) #name, static const char * const directive_names[] = { -DIRECTIVE_TABLE + DIRECTIVE_TABLE + + /* Русские синонимы для подсказок */ + "определить", + "включить", + "если", + "если_определен", + "если_не_определен", + "иначе_если", + "иначе", + "конец_если", + "отменить", + "ошибка", + "предупреждение", + "прагма", + "строка", + "включить_след", + "импорт", + NULL }; #undef D @@ -459,6 +494,7 @@ _cpp_handle_directive (cpp_reader *pfile, bool indented) if (dname->type == CPP_NAME) { + /* Сначала проверяем стандартные директивы по is_directive. */ if (dname->val.node.node->is_directive) { dir = &dtable[dname->val.node.node->directive_index]; @@ -469,6 +505,31 @@ _cpp_handle_directive (cpp_reader *pfile, bool indented) && CPP_OPTION (pfile, std)) dir = 0; } +else + { + /* Если не нашли по is_directive, ищем русский синоним в dtable. */ + const uchar *name = NODE_NAME (dname->val.node.node); + size_t len = NODE_LEN (dname->val.node.node); + + /* ОТЛАДКА: выводим имя и длину искомой директивы */ + fprintf (stderr, "DEBUG: Looking for directive '%.*s' (len=%zu)\n", + (int)len, name, len); + + for (unsigned int i = 0; i < ARRAY_SIZE (dtable); i++) + { + /* ОТЛАДКА: выводим каждую запись в dtable */ + fprintf (stderr, "DEBUG: dtable[%u] = '%.*s' (len=%hu)\n", + i, (int)dtable[i].length, dtable[i].name, dtable[i].length); + + if (dtable[i].length == len + && memcmp (dtable[i].name, name, len) == 0) + { + fprintf (stderr, "DEBUG: FOUND! i=%u\n", i); + dir = &dtable[i]; + break; + } + } + } } /* We do not recognize the # followed by a number extension in assembler code. */ @@ -2171,8 +2232,9 @@ do_elif (cpp_reader *pfile) } else { - if (pfile->directive == &dtable[T_ELIF]) - pfile->state.skipping = !_cpp_parse_expr (pfile, false); + if (pfile->directive == &dtable[T_ELIF] + || pfile->directive->handler == do_elif) + pfile->state.skipping = !_cpp_parse_expr (pfile, false); else { cpp_hashnode *node = lex_macro_node (pfile, false); @@ -2813,6 +2875,16 @@ _cpp_init_directives (cpp_reader *pfile) node->is_directive = 1; node->directive_index = i; } + + /* Добавляем русские синонимы в хеш-таблицу. + Они не должны иметь is_directive, потому что мы будем + искать их напрямую в dtable[] по имени. */ + const char *russian_aliases[] = { + "определить", "включить", "если", "если_определен", + "если_не_определен", "иначе_если", "иначе", + "конец_если", "отменить", "ошибка", "предупреждение", + "прагма", "строка", "включить_след", "импорт" + }; } /* Extract header file from a bracket include. Parsing starts after '<'. diff --git a/libcpp/expr.cc b/libcpp/expr.cc index 815eb137a99..4008d222560 100644 --- a/libcpp/expr.cc +++ b/libcpp/expr.cc @@ -1174,6 +1174,16 @@ parse_defined (cpp_reader *pfile) return result; } +/* Handle meeting "определено" in a preprocessor expression (Russian synonym). */ +static cpp_num +parse_defined_ru (cpp_reader *pfile) +{ + /* Просто вызываем parse_defined, так как логика обработки идентична. + Разница только в имени оператора, которое используется только в + сообщениях об ошибках, поэтому переиспользуем существующую функцию. */ + return parse_defined (pfile); +} + /* Convert a token into a CPP_NUMBER (an interpreted preprocessing number or character constant, or the result of the "defined" or "#" operators). */ @@ -1241,6 +1251,9 @@ eval_token (cpp_reader *pfile, const cpp_token *token, case CPP_NAME: if (token->val.node.node == pfile->spec_nodes.n_defined) return parse_defined (pfile); + /* Русский синоним "определено" */ + else if (token->val.node.node == pfile->spec_nodes.n_defined_ru) + return parse_defined (pfile); else if (CPP_OPTION (pfile, true_false) && (token->val.node.node == pfile->spec_nodes.n_true || token->val.node.node == pfile->spec_nodes.n_false)) diff --git a/libcpp/init.cc b/libcpp/init.cc index 54fc9236d38..ea647e5b544 100644 --- a/libcpp/init.cc +++ b/libcpp/init.cc @@ -309,6 +309,9 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, _cpp_init_hashtable (pfile, table, extra_table); + pfile->spec_nodes.n_defined_ru = cpp_lookup (pfile, UC"определено", + sizeof "определено" - 1); + return pfile; } @@ -418,14 +421,22 @@ struct builtin_macro static const struct builtin_macro builtin_array[] = { B("__TIMESTAMP__", BT_TIMESTAMP, false), + B("__ВРЕМЯ_ФАЙЛА__", BT_TIMESTAMP, false), B("__TIME__", BT_TIME, false), + B("__ВРЕМЯ__", BT_TIME, false), B("__DATE__", BT_DATE, false), + B("__ДАТА__", BT_DATE, false), B("__FILE__", BT_FILE, false), + B("__ФАЙЛ__", BT_FILE, false), B("__FILE_NAME__", BT_FILE_NAME, false), B("__BASE_FILE__", BT_BASE_FILE, false), + B("__БАЗОВЫЙ_ФАЙЛ__", BT_BASE_FILE, false), B("__LINE__", BT_SPECLINE, true), + B("__ЛИНИЯ__", BT_SPECLINE, true), B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true), B("__COUNTER__", BT_COUNTER, true), + B("__СЧЁТЧИК__", BT_COUNTER, true), + B("__СЧЕТЧИК__", BT_COUNTER, true), /* Make sure to update the list of built-in function-like macros in traditional.cc: fun_like_macro() when adding more following */ diff --git a/libcpp/internal.h b/libcpp/internal.h index a20215c5709..538013d980f 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -297,6 +297,7 @@ struct lexer_state struct spec_nodes { cpp_hashnode *n_defined; /* defined operator */ + cpp_hashnode *n_defined_ru; /* русский синоним "определено" */ cpp_hashnode *n_true; /* C++ keyword true */ cpp_hashnode *n_false; /* C++ keyword false */ cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ diff --git a/libcpp/lex.cc b/libcpp/lex.cc index c9e44e6cccc..e6743393116 100644 --- a/libcpp/lex.cc +++ b/libcpp/lex.cc @@ -2085,6 +2085,40 @@ forms_identifier_p (cpp_reader *pfile, int first, return true; } + /* ================================================================ + ДОБАВЛЕНО: Проверка на русские буквы в UTF-8 + ================================================================ */ + if (*buffer->cur == 0xD0 || *buffer->cur == 0xD1) + { + unsigned char first = *buffer->cur; + unsigned char second = *(buffer->cur + 1); + + /* Диапазоны русских букв в UTF-8: + А-Я: D0 90 - D0 AF + а-я: D1 80 - D1 8F + Ё: D0 81 + ё: D1 91 + */ + if (first == 0xD0 && second >= 0x90 && second <= 0xBF) + { + buffer->cur += 2; + return true; + } + if (first == 0xD1 && second >= 0x80 && second <= 0x8F) + { + buffer->cur += 2; + return true; + } + if (first == 0xD0 && (second == 0x81 || second == 0x91)) + { + buffer->cur += 2; + return true; + } + } + /* ================================================================ + КОНЕЦ ДОБАВЛЕННОГО БЛОКА + ================================================================ */ + /* Is this a syntactically valid UCN or a valid UTF-8 char? */ if (CPP_OPTION (pfile, extended_identifiers)) {
? Дизассемблированные привет мир
me@me-Aspire-5742G:~/Документы/rusi/rusi$ objdump -d привет_chibicc привет_chibicc: формат файла elf64-x86-64 Дизассемблирование раздела .init: 0000000000401000 <_init>: 401000: f3 0f 1e fa endbr64 401004: 48 83 ec 08 sub $0x8,%rsp 401008: 48 8b 05 d1 2f 00 00 mov 0x2fd1(%rip),%rax # 403fe0 <__gmon_start__> 40100f: 48 85 c0 test %rax,%rax 401012: 74 02 je 401016 <_init+0x16> 401014: ff d0 call *%rax 401016: 48 83 c4 08 add $0x8,%rsp 40101a: c3 ret Дизассемблирование раздела .text: 0000000000401020 <_start>: 401020: f3 0f 1e fa endbr64 401024: 31 ed xor %ebp,%ebp 401026: 49 89 d1 mov %rdx,%r9 401029: 5e pop %rsi 40102a: 48 89 e2 mov %rsp,%rdx 40102d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 401031: 50 push %rax 401032: 54 push %rsp 401033: 45 31 c0 xor %r8d,%r8d 401036: 31 c9 xor %ecx,%ecx 401038: 48 c7 c7 06 11 40 00 mov $0x401106,%rdi 40103f: ff 15 8b 2f 00 00 call *0x2f8b(%rip) # 403fd0 <__libc_start_main@GLIBC_2.34> 401045: f4 hlt 401046: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40104d: 00 00 00 0000000000401050 <_dl_relocate_static_pie>: 401050: f3 0f 1e fa endbr64 401054: c3 ret 401055: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40105c: 00 00 00 40105f: 90 nop 0000000000401060 <deregister_tm_clones>: 401060: b8 d8 41 40 00 mov $0x4041d8,%eax 401065: 48 3d d8 41 40 00 cmp $0x4041d8,%rax 40106b: 74 13 je 401080 <deregister_tm_clones+0x20> 40106d: b8 00 00 00 00 mov $0x0,%eax 401072: 48 85 c0 test %rax,%rax 401075: 74 09 je 401080 <deregister_tm_clones+0x20> 401077: bf d8 41 40 00 mov $0x4041d8,%edi 40107c: ff e0 jmp *%rax 40107e: 66 90 xchg %ax,%ax 401080: c3 ret 401081: 0f 1f 40 00 nopl 0x0(%rax) 401085: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 40108c: 00 00 00 00 0000000000401090 <register_tm_clones>: 401090: be d8 41 40 00 mov $0x4041d8,%esi 401095: 48 81 ee d8 41 40 00 sub $0x4041d8,%rsi 40109c: 48 89 f0 mov %rsi,%rax 40109f: 48 c1 ee 3f shr $0x3f,%rsi 4010a3: 48 c1 f8 03 sar $0x3,%rax 4010a7: 48 01 c6 add %rax,%rsi 4010aa: 48 d1 fe sar $1,%rsi 4010ad: 74 11 je 4010c0 <register_tm_clones+0x30> 4010af: b8 00 00 00 00 mov $0x0,%eax 4010b4: 48 85 c0 test %rax,%rax 4010b7: 74 07 je 4010c0 <register_tm_clones+0x30> 4010b9: bf d8 41 40 00 mov $0x4041d8,%edi 4010be: ff e0 jmp *%rax 4010c0: c3 ret 4010c1: 0f 1f 40 00 nopl 0x0(%rax) 4010c5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 4010cc: 00 00 00 00 00000000004010d0 <__do_global_dtors_aux>: 4010d0: f3 0f 1e fa endbr64 4010d4: 80 3d fa 30 00 00 00 cmpb $0x0,0x30fa(%rip) # 4041d5 <completed.0> 4010db: 75 13 jne 4010f0 <__do_global_dtors_aux+0x20> 4010dd: 55 push %rbp 4010de: 48 89 e5 mov %rsp,%rbp 4010e1: e8 7a ff ff ff call 401060 <deregister_tm_clones> 4010e6: c6 05 e8 30 00 00 01 movb $0x1,0x30e8(%rip) # 4041d5 <completed.0> 4010ed: 5d pop %rbp 4010ee: c3 ret 4010ef: 90 nop 4010f0: c3 ret 4010f1: 0f 1f 40 00 nopl 0x0(%rax) 4010f5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 4010fc: 00 00 00 00 0000000000401100 <frame_dummy>: 401100: f3 0f 1e fa endbr64 401104: eb 8a jmp 401090 <register_tm_clones> 0000000000401106 <главн>: 401106: 55 push %rbp 401107: 48 89 e5 mov %rsp,%rbp 40110a: 48 83 ec 10 sub $0x10,%rsp 40110e: 48 89 65 f8 mov %rsp,-0x8(%rbp) 401112: 48 8d 05 f7 2e 00 00 lea 0x2ef7(%rip),%rax # 404010 <__dso_handle+0x8> 401119: 50 push %rax 40111a: 48 8b 05 b7 2e 00 00 mov 0x2eb7(%rip),%rax # 403fd8 <printf@GLIBC_2.2.5> 401121: 5f pop %rdi 401122: 49 89 c2 mov %rax,%r10 401125: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40112c: 41 ff d2 call *%r10 40112f: 48 83 c4 00 add $0x0,%rsp 401133: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40113a: eb 07 jmp 401143 <главн+0x3d> 40113c: 48 c7 c0 00 00 00 00 mov $0x0,%rax 401143: 48 89 ec mov %rbp,%rsp 401146: 5d pop %rbp 401147: c3 ret 0000000000401148 <__va_read_from_fp>: 401148: 55 push %rbp 401149: 48 89 e5 mov %rsp,%rbp 40114c: 48 83 ec 30 sub $0x30,%rsp 401150: 48 89 65 e8 mov %rsp,-0x18(%rbp) 401154: 48 89 7d e0 mov %rdi,-0x20(%rbp) 401158: 89 75 dc mov %esi,-0x24(%rbp) 40115b: 89 55 d8 mov %edx,-0x28(%rbp) 40115e: 48 8d 45 e0 lea -0x20(%rbp),%rax 401162: 48 8b 00 mov (%rax),%rax 401165: 48 83 c0 04 add $0x4,%rax 401169: 48 63 00 movslq (%rax),%rax 40116c: 50 push %rax 40116d: 48 c7 c0 70 00 00 00 mov $0x70,%rax 401174: 5f pop %rdi 401175: 39 f8 cmp %edi,%eax 401177: 0f 96 c0 setbe %al 40117a: 48 0f b6 c0 movzbq %al,%rax 40117e: 83 f8 00 cmp $0x0,%eax 401181: 74 3a je 4011bd <__va_read_from_fp+0x75> 401183: 48 8d 45 d8 lea -0x28(%rbp),%rax 401187: 48 63 00 movslq (%rax),%rax 40118a: 50 push %rax 40118b: 48 8d 45 dc lea -0x24(%rbp),%rax 40118f: 48 63 00 movslq (%rax),%rax 401192: 50 push %rax 401193: 48 8d 45 e0 lea -0x20(%rbp),%rax 401197: 48 8b 00 mov (%rax),%rax 40119a: 50 push %rax 40119b: 48 8d 05 ac 01 00 00 lea 0x1ac(%rip),%rax # 40134e <__va_read_from_stack> 4011a2: 5f pop %rdi 4011a3: 5e pop %rsi 4011a4: 5a pop %rdx 4011a5: 49 89 c2 mov %rax,%r10 4011a8: 48 c7 c0 00 00 00 00 mov $0x0,%rax 4011af: 41 ff d2 call *%r10 4011b2: 48 83 c4 00 add $0x0,%rsp 4011b6: e9 8b 00 00 00 jmp 401246 <__va_read_from_fp+0xfe> 4011bb: eb 00 jmp 4011bd <__va_read_from_fp+0x75> 4011bd: 48 c7 c1 08 00 00 00 mov $0x8,%rcx 4011c4: 48 8d 7d f0 lea -0x10(%rbp),%rdi 4011c8: b0 00 mov $0x0,%al 4011ca: f3 aa rep stos %al,(%rdi) 4011cc: 48 8d 45 f0 lea -0x10(%rbp),%rax 4011d0: 50 push %rax 4011d1: 48 c7 c0 01 00 00 00 mov $0x1,%rax 4011d8: 50 push %rax 4011d9: 48 8d 45 e0 lea -0x20(%rbp),%rax 4011dd: 48 8b 00 mov (%rax),%rax 4011e0: 48 83 c0 04 add $0x4,%rax 4011e4: 48 63 00 movslq (%rax),%rax 4011e7: 89 c0 mov %eax,%eax 4011e9: 5f pop %rdi 4011ea: 48 0f af c7 imul %rdi,%rax 4011ee: 50 push %rax 4011ef: 48 8d 45 e0 lea -0x20(%rbp),%rax 4011f3: 48 8b 00 mov (%rax),%rax 4011f6: 48 83 c0 10 add $0x10,%rax 4011fa: 48 8b 00 mov (%rax),%rax 4011fd: 5f pop %rdi 4011fe: 48 01 f8 add %rdi,%rax 401201: 5f pop %rdi 401202: 48 89 07 mov %rax,(%rdi) 401205: 48 8d 45 f8 lea -0x8(%rbp),%rax 401209: 50 push %rax 40120a: 48 8d 45 e0 lea -0x20(%rbp),%rax 40120e: 48 8b 00 mov (%rax),%rax 401211: 5f pop %rdi 401212: 48 89 07 mov %rax,(%rdi) 401215: 48 8d 45 f8 lea -0x8(%rbp),%rax 401219: 48 8b 00 mov (%rax),%rax 40121c: 48 83 c0 04 add $0x4,%rax 401220: 50 push %rax 401221: 48 c7 c0 08 00 00 00 mov $0x8,%rax 401228: 50 push %rax 401229: 48 8d 45 f8 lea -0x8(%rbp),%rax 40122d: 48 8b 00 mov (%rax),%rax 401230: 48 83 c0 04 add $0x4,%rax 401234: 48 63 00 movslq (%rax),%rax 401237: 5f pop %rdi 401238: 01 f8 add %edi,%eax 40123a: 5f pop %rdi 40123b: 89 07 mov %eax,(%rdi) 40123d: 48 8d 45 f0 lea -0x10(%rbp),%rax 401241: 48 8b 00 mov (%rax),%rax 401244: eb 00 jmp 401246 <__va_read_from_fp+0xfe> 401246: 48 89 ec mov %rbp,%rsp 401249: 5d pop %rbp 40124a: c3 ret 000000000040124b <__va_read_from_gp>: 40124b: 55 push %rbp 40124c: 48 89 e5 mov %rsp,%rbp 40124f: 48 83 ec 30 sub $0x30,%rsp 401253: 48 89 65 e8 mov %rsp,-0x18(%rbp) 401257: 48 89 7d e0 mov %rdi,-0x20(%rbp) 40125b: 89 75 dc mov %esi,-0x24(%rbp) 40125e: 89 55 d8 mov %edx,-0x28(%rbp) 401261: 48 8d 45 e0 lea -0x20(%rbp),%rax 401265: 48 8b 00 mov (%rax),%rax 401268: 48 83 c0 00 add $0x0,%rax 40126c: 48 63 00 movslq (%rax),%rax 40126f: 50 push %rax 401270: 48 c7 c0 30 00 00 00 mov $0x30,%rax 401277: 5f pop %rdi 401278: 39 f8 cmp %edi,%eax 40127a: 0f 96 c0 setbe %al 40127d: 48 0f b6 c0 movzbq %al,%rax 401281: 83 f8 00 cmp $0x0,%eax 401284: 74 3a je 4012c0 <__va_read_from_gp+0x75> 401286: 48 8d 45 d8 lea -0x28(%rbp),%rax 40128a: 48 63 00 movslq (%rax),%rax 40128d: 50 push %rax 40128e: 48 8d 45 dc lea -0x24(%rbp),%rax 401292: 48 63 00 movslq (%rax),%rax 401295: 50 push %rax 401296: 48 8d 45 e0 lea -0x20(%rbp),%rax 40129a: 48 8b 00 mov (%rax),%rax 40129d: 50 push %rax 40129e: 48 8d 05 a9 00 00 00 lea 0xa9(%rip),%rax # 40134e <__va_read_from_stack> 4012a5: 5f pop %rdi 4012a6: 5e pop %rsi 4012a7: 5a pop %rdx 4012a8: 49 89 c2 mov %rax,%r10 4012ab: 48 c7 c0 00 00 00 00 mov $0x0,%rax 4012b2: 41 ff d2 call *%r10 4012b5: 48 83 c4 00 add $0x0,%rsp 4012b9: e9 8b 00 00 00 jmp 401349 <__va_read_from_gp+0xfe> 4012be: eb 00 jmp 4012c0 <__va_read_from_gp+0x75> 4012c0: 48 c7 c1 08 00 00 00 mov $0x8,%rcx 4012c7: 48 8d 7d f0 lea -0x10(%rbp),%rdi 4012cb: b0 00 mov $0x0,%al 4012cd: f3 aa rep stos %al,(%rdi) 4012cf: 48 8d 45 f0 lea -0x10(%rbp),%rax 4012d3: 50 push %rax 4012d4: 48 c7 c0 01 00 00 00 mov $0x1,%rax 4012db: 50 push %rax 4012dc: 48 8d 45 e0 lea -0x20(%rbp),%rax 4012e0: 48 8b 00 mov (%rax),%rax 4012e3: 48 83 c0 00 add $0x0,%rax 4012e7: 48 63 00 movslq (%rax),%rax 4012ea: 89 c0 mov %eax,%eax 4012ec: 5f pop %rdi 4012ed: 48 0f af c7 imul %rdi,%rax 4012f1: 50 push %rax 4012f2: 48 8d 45 e0 lea -0x20(%rbp),%rax 4012f6: 48 8b 00 mov (%rax),%rax 4012f9: 48 83 c0 10 add $0x10,%rax 4012fd: 48 8b 00 mov (%rax),%rax 401300: 5f pop %rdi 401301: 48 01 f8 add %rdi,%rax 401304: 5f pop %rdi 401305: 48 89 07 mov %rax,(%rdi) 401308: 48 8d 45 f8 lea -0x8(%rbp),%rax 40130c: 50 push %rax 40130d: 48 8d 45 e0 lea -0x20(%rbp),%rax 401311: 48 8b 00 mov (%rax),%rax 401314: 5f pop %rdi 401315: 48 89 07 mov %rax,(%rdi) 401318: 48 8d 45 f8 lea -0x8(%rbp),%rax 40131c: 48 8b 00 mov (%rax),%rax 40131f: 48 83 c0 00 add $0x0,%rax 401323: 50 push %rax 401324: 48 c7 c0 08 00 00 00 mov $0x8,%rax 40132b: 50 push %rax 40132c: 48 8d 45 f8 lea -0x8(%rbp),%rax 401330: 48 8b 00 mov (%rax),%rax 401333: 48 83 c0 00 add $0x0,%rax 401337: 48 63 00 movslq (%rax),%rax 40133a: 5f pop %rdi 40133b: 01 f8 add %edi,%eax 40133d: 5f pop %rdi 40133e: 89 07 mov %eax,(%rdi) 401340: 48 8d 45 f0 lea -0x10(%rbp),%rax 401344: 48 8b 00 mov (%rax),%rax 401347: eb 00 jmp 401349 <__va_read_from_gp+0xfe> 401349: 48 89 ec mov %rbp,%rsp 40134c: 5d pop %rbp 40134d: c3 ret 000000000040134e <__va_read_from_stack>: 40134e: 55 push %rbp 40134f: 48 89 e5 mov %rsp,%rbp 401352: 48 83 ec 20 sub $0x20,%rsp 401356: 48 89 65 f0 mov %rsp,-0x10(%rbp) 40135a: 48 89 7d e8 mov %rdi,-0x18(%rbp) 40135e: 89 75 e4 mov %esi,-0x1c(%rbp) 401361: 89 55 e0 mov %edx,-0x20(%rbp) 401364: 48 c7 c1 08 00 00 00 mov $0x8,%rcx 40136b: 48 8d 7d f8 lea -0x8(%rbp),%rdi 40136f: b0 00 mov $0x0,%al 401371: f3 aa rep stos %al,(%rdi) 401373: 48 8d 45 f8 lea -0x8(%rbp),%rax 401377: 50 push %rax 401378: 48 8d 45 e8 lea -0x18(%rbp),%rax 40137c: 48 8b 00 mov (%rax),%rax 40137f: 48 83 c0 08 add $0x8,%rax 401383: 48 8b 00 mov (%rax),%rax 401386: 5f pop %rdi 401387: 48 89 07 mov %rax,(%rdi) 40138a: 48 8d 45 e0 lea -0x20(%rbp),%rax 40138e: 48 63 00 movslq (%rax),%rax 401391: 50 push %rax 401392: 48 c7 c0 08 00 00 00 mov $0x8,%rax 401399: 5f pop %rdi 40139a: 39 f8 cmp %edi,%eax 40139c: 0f 9c c0 setl %al 40139f: 48 0f b6 c0 movzbq %al,%rax 4013a3: 83 f8 00 cmp $0x0,%eax 4013a6: 74 54 je 4013fc <__va_read_from_stack+0xae> 4013a8: 48 8d 45 f8 lea -0x8(%rbp),%rax 4013ac: 50 push %rax 4013ad: 48 c7 c0 10 00 00 00 mov $0x10,%rax 4013b4: 48 63 c0 movslq %eax,%rax 4013b7: 50 push %rax 4013b8: 48 c7 c0 10 00 00 00 mov $0x10,%rax 4013bf: 48 63 c0 movslq %eax,%rax 4013c2: 50 push %rax 4013c3: 48 c7 c0 01 00 00 00 mov $0x1,%rax 4013ca: 50 push %rax 4013cb: 48 c7 c0 0f 00 00 00 mov $0xf,%rax 4013d2: 48 63 c0 movslq %eax,%rax 4013d5: 5f pop %rdi 4013d6: 48 0f af c7 imul %rdi,%rax 4013da: 50 push %rax 4013db: 48 8d 45 f8 lea -0x8(%rbp),%rax 4013df: 48 8b 00 mov (%rax),%rax 4013e2: 5f pop %rdi 4013e3: 48 01 f8 add %rdi,%rax 4013e6: 5f pop %rdi 4013e7: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 4013ee: 48 f7 f7 div %rdi 4013f1: 5f pop %rdi 4013f2: 48 0f af c7 imul %rdi,%rax 4013f6: 5f pop %rdi 4013f7: 48 89 07 mov %rax,(%rdi) 4013fa: eb 00 jmp 4013fc <__va_read_from_stack+0xae> 4013fc: 48 8d 45 e8 lea -0x18(%rbp),%rax 401400: 48 8b 00 mov (%rax),%rax 401403: 48 83 c0 08 add $0x8,%rax 401407: 50 push %rax 401408: 48 c7 c0 08 00 00 00 mov $0x8,%rax 40140f: 48 63 c0 movslq %eax,%rax 401412: 50 push %rax 401413: 48 c7 c0 08 00 00 00 mov $0x8,%rax 40141a: 48 63 c0 movslq %eax,%rax 40141d: 50 push %rax 40141e: 48 c7 c0 07 00 00 00 mov $0x7,%rax 401425: 48 63 c0 movslq %eax,%rax 401428: 50 push %rax 401429: 48 8d 45 e4 lea -0x1c(%rbp),%rax 40142d: 48 63 00 movslq (%rax),%rax 401430: 48 63 c0 movslq %eax,%rax 401433: 50 push %rax 401434: 48 8d 45 f8 lea -0x8(%rbp),%rax 401438: 48 8b 00 mov (%rax),%rax 40143b: 5f pop %rdi 40143c: 48 01 f8 add %rdi,%rax 40143f: 5f pop %rdi 401440: 48 01 f8 add %rdi,%rax 401443: 5f pop %rdi 401444: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 40144b: 48 f7 f7 div %rdi 40144e: 5f pop %rdi 40144f: 48 0f af c7 imul %rdi,%rax 401453: 5f pop %rdi 401454: 48 89 07 mov %rax,(%rdi) 401457: 48 8d 45 f8 lea -0x8(%rbp),%rax 40145b: 48 8b 00 mov (%rax),%rax 40145e: eb 00 jmp 401460 <__va_read_from_stack+0x112> 401460: 48 89 ec mov %rbp,%rsp 401463: 5d pop %rbp 401464: c3 ret Дизассемблирование раздела .fini: 0000000000401468 <_fini>: 401468: f3 0f 1e fa endbr64 40146c: 48 83 ec 08 sub $0x8,%rsp 401470: 48 83 c4 08 add $0x8,%rsp 401474: c3 ret me@me-Aspire-5742G:~/Документы/rusi/rusi$
me@me-Aspire-5742G:~/Документы/rusi/rusi$ objdump -d привет_gcc привет_gcc: формат файла elf64-x86-64 Дизассемблирование раздела .init: 0000000000401000 <_init>: 401000: f3 0f 1e fa endbr64 401004: 48 83 ec 08 sub $0x8,%rsp 401008: 48 8b 05 d1 2f 00 00 mov 0x2fd1(%rip),%rax # 403fe0 <__gmon_start__> 40100f: 48 85 c0 test %rax,%rax 401012: 74 02 je 401016 <_init+0x16> 401014: ff d0 call *%rax 401016: 48 83 c4 08 add $0x8,%rsp 40101a: c3 ret Дизассемблирование раздела .plt: 0000000000401020 <puts@plt-0x10>: 401020: ff 35 ca 2f 00 00 push 0x2fca(%rip) # 403ff0 <_GLOBAL_OFFSET_TABLE_+0x8> 401026: ff 25 cc 2f 00 00 jmp *0x2fcc(%rip) # 403ff8 <_GLOBAL_OFFSET_TABLE_+0x10> 40102c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000401030 <puts@plt>: 401030: ff 25 ca 2f 00 00 jmp *0x2fca(%rip) # 404000 <puts@GLIBC_2.2.5> 401036: 68 00 00 00 00 push $0x0 40103b: e9 e0 ff ff ff jmp 401020 <_init+0x20> Дизассемблирование раздела .text: 0000000000401040 <main>: 401040: 48 83 ec 08 sub $0x8,%rsp 401044: bf 04 20 40 00 mov $0x402004,%edi 401049: e8 e2 ff ff ff call 401030 <puts@plt> 40104e: 31 c0 xor %eax,%eax 401050: 48 83 c4 08 add $0x8,%rsp 401054: c3 ret 401055: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40105c: 00 00 00 40105f: 90 nop 0000000000401060 <_start>: 401060: f3 0f 1e fa endbr64 401064: 31 ed xor %ebp,%ebp 401066: 49 89 d1 mov %rdx,%r9 401069: 5e pop %rsi 40106a: 48 89 e2 mov %rsp,%rdx 40106d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 401071: 50 push %rax 401072: 54 push %rsp 401073: 45 31 c0 xor %r8d,%r8d 401076: 31 c9 xor %ecx,%ecx 401078: 48 c7 c7 40 10 40 00 mov $0x401040,%rdi 40107f: ff 15 53 2f 00 00 call *0x2f53(%rip) # 403fd8 <__libc_start_main@GLIBC_2.34> 401085: f4 hlt 401086: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40108d: 00 00 00 0000000000401090 <_dl_relocate_static_pie>: 401090: f3 0f 1e fa endbr64 401094: c3 ret 401095: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40109c: 00 00 00 40109f: 90 nop 00000000004010a0 <deregister_tm_clones>: 4010a0: b8 18 40 40 00 mov $0x404018,%eax 4010a5: 48 3d 18 40 40 00 cmp $0x404018,%rax 4010ab: 74 13 je 4010c0 <deregister_tm_clones+0x20> 4010ad: b8 00 00 00 00 mov $0x0,%eax 4010b2: 48 85 c0 test %rax,%rax 4010b5: 74 09 je 4010c0 <deregister_tm_clones+0x20> 4010b7: bf 18 40 40 00 mov $0x404018,%edi 4010bc: ff e0 jmp *%rax 4010be: 66 90 xchg %ax,%ax 4010c0: c3 ret 4010c1: 0f 1f 40 00 nopl 0x0(%rax) 4010c5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 4010cc: 00 00 00 00 00000000004010d0 <register_tm_clones>: 4010d0: be 18 40 40 00 mov $0x404018,%esi 4010d5: 48 81 ee 18 40 40 00 sub $0x404018,%rsi 4010dc: 48 89 f0 mov %rsi,%rax 4010df: 48 c1 ee 3f shr $0x3f,%rsi 4010e3: 48 c1 f8 03 sar $0x3,%rax 4010e7: 48 01 c6 add %rax,%rsi 4010ea: 48 d1 fe sar $1,%rsi 4010ed: 74 11 je 401100 <register_tm_clones+0x30> 4010ef: b8 00 00 00 00 mov $0x0,%eax 4010f4: 48 85 c0 test %rax,%rax 4010f7: 74 07 je 401100 <register_tm_clones+0x30> 4010f9: bf 18 40 40 00 mov $0x404018,%edi 4010fe: ff e0 jmp *%rax 401100: c3 ret 401101: 0f 1f 40 00 nopl 0x0(%rax) 401105: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 40110c: 00 00 00 00 0000000000401110 <__do_global_dtors_aux>: 401110: f3 0f 1e fa endbr64 401114: 80 3d fd 2e 00 00 00 cmpb $0x0,0x2efd(%rip) # 404018 <__TMC_END__> 40111b: 75 13 jne 401130 <__do_global_dtors_aux+0x20> 40111d: 55 push %rbp 40111e: 48 89 e5 mov %rsp,%rbp 401121: e8 7a ff ff ff call 4010a0 <deregister_tm_clones> 401126: c6 05 eb 2e 00 00 01 movb $0x1,0x2eeb(%rip) # 404018 <__TMC_END__> 40112d: 5d pop %rbp 40112e: c3 ret 40112f: 90 nop 401130: c3 ret 401131: 0f 1f 40 00 nopl 0x0(%rax) 401135: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 40113c: 00 00 00 00 0000000000401140 <frame_dummy>: 401140: f3 0f 1e fa endbr64 401144: eb 8a jmp 4010d0 <register_tm_clones> Дизассемблирование раздела .fini: 0000000000401148 <_fini>: 401148: f3 0f 1e fa endbr64 40114c: 48 83 ec 08 sub $0x8,%rsp 401150: 48 83 c4 08 add $0x8,%rsp 401154: c3 ret me@me-Aspire-5742G:~/Документы/rusi/rusi$
? Еще один тестовый пример на плюсах
класс Фигура { открыт: вирт пусто описать() { std::cout << "Фигура" << std::endl; } вирт ~Фигура() {} }; класс Круг : открыт Фигура { открыт: двойн радиус; Круг(двойн р) : радиус(р) {} пусто описать() override { std::cout << "Круг радиусом " << радиус << std::endl; } }; шаблон<имя_типа T> T удвоить(T значение) { возврат значение * 2; } цел главн() { Круг к(5.0); к.описать(); std::cout << "Удвоенное 21 = " << удвоить(21) << std::endl; std::cout << "Удвоенное 1.5 = " << удвоить(1.5) << std::endl; возврат 0; }
me@me-Aspire-5742G:/usr/local/gcc-rus/bin/g++ -std=c++20 /tmp/руси_плюс_плюс.cpp -o /tmp/руси_плюс_плюс 2>&1 | head -30 me@me-Aspire-5742G:~/RUSI-build/rgcc/тесты$ /tmp/руси_плюс_плюс Круг радиусом 5 Удвоенное 21 = 42 Удвоенное 1.5 = 3
Промпты для анализа статьи
Тем, кто хочет извлечь дополнительную информацию для размышлений или почерпнуть филосовских и технических взглядов на проект. Загружаем текст статьи в контекст и просим:
Оценку с позиции кибернетики.
Анализ с позиции ТРИЗ.
Провести анализ текста с позиций эвристики.
Анализ написанного с позиции теории систем.
Оценить написанное с позиции философии open source.
Оценка с позиций аналитической философии техники.
Послесловие
Этот проект начинался как спортивный интерес. «Смогу ли я одолеть GCC?» Смог, получилось, заработало. И результат радует.
Из нишевого форка chibicc выросли три оригинальных синтаксиса: Руси (Си), Руси++ (C++), Объектный-Руси (Objective-C). Все три - промышленного уровня, на базе GCC 14.2.
Это не «русский язык программирования с нуля». Это теперь двойной Си. Это билингвальный интерфейс к существующему языку. Не «вместо», а «вместе».
Комментарии (105)

SilverTrouse
17.10.2026 18:30а есть поддержка модулей? там "имортировать модудль РУС;" и "экспортировать модудль РУС;" ?

serafims
17.10.2026 18:30Грустно выглядит, за счёт сокращений типа "цел" (что мешает писать "целое") слов теряется стройность, которая для англоговорящих получается.

serafims
17.10.2026 18:30С применением спец клавиатур, спец символов по мне так было бы интересно интегрировать специальные иероглифы в код, чтобы сократить визуальный мусор от служебных слов и сделать акцент на логике кода.

vadimr
17.10.2026 18:30Язык APL был уже давно.
Но некоторая правда тут в том, что всякие там состояния конечных автоматов и прочие абстрактные символы бывает красиво обозначать китайскими иероглифами. Хотя и не очень человеколюбиво.
Русский же язык с его флективностью объективно плохо подходит для лексической базы языков программирования.

randomsimplenumber
17.10.2026 18:30состояния конечных автоматов и прочие абстрактные символы бывает красиво обозначать китайскими иероглифами
Красивое
не очень человеколюбиво
Китайцы будут недовольны ;)

Blacpaul57
17.10.2026 18:30В русском языке слова длиннее и имеют падежи, поэтому в лоб скопировать лаконичность английского C не выходит. Если писать полные слова вроде безвозвратный или константа, строчки кода уедут за пределы экрана на первом же вложенном цикле. Отсюда и рождаются эти странные обрубки, от которых дергается глаз

spacediver
17.10.2026 18:30Прикольно, не ново, но, кажется, уже окончательно поздняк.
Исходными кодами на «языках программирования высокого уровня» теперь будут заниматься
LLMБЯМ-ки, а им лучше жевать то, на чём написан колоссальный массив, на котором они были обучены, массив, написанный в уходящую эпоху, когда исходные программы ещё писались руками…
Wesha
17.10.2026 18:30в уходящую эпоху, когда исходные программы ещё писались руками…
(Меланхолично:) Не знаю, кто как — а я вот программы пишу головой.
Руками я переношу их из головы в компьютер.

IvaYan
17.10.2026 18:30Честно говоря, не очень ясен практический смысл в этой "русификации". Ну то есть, какую задачу это решает. Если цель в том, чтобы просто развлечься и посмотреть, как в GCC переименовать ключевые слова, то окей, вопросов нет, но в остальном, я смысла не вижу, если честно.
Для профессиональных программистов это не имеет смысла, они о смысле ключевых слов в языке-оригинале вряд ли задумываются. А при обучении программированию, незнание смысла слова void вряд ли является основным препятствием.
Такой стандарт может быть принят для использования в … - везде, где требуется русскоязычная документация и код.
А где требуется русскоязычный код? Вот именно прям чтобы требуется и без этого нельзя. И что мешает иметь русскоязычную документацию если код использует латиницу?
Отрасли
Приборостроение - уникальные приборы, измерительная техника
Робототехника - управление роботами
Системы связи - телекоммуникационное оборудование
Транспорт - встроенные системы автомобилей, поездов, самолётов
Как эти отрасли выиграют от перевода ключевых слов ПРОМПТом?

randomsimplenumber
17.10.2026 18:30незнание смысла слова void
А зачем знать смысл? Ключевые слова не используются как слова английского языка, а программа - не текст на английском. Плохо представляю, как программист может не запомнить 20 ключевых слов. Разве что он латиницы в жизни не видел, и для него незнакомые буквы совсем не складываются в слова.. это называется дислексия емнип.

IvaYan
17.10.2026 18:30А зачем знать смысл? Ключевые слова не используются как слова английского языка, а программа - не текст на английском.
Я ровно об этом и говорю. При обучении программированию проблема вовсе не в том, что человек не знает значения слова void, а значит замена на слово "пустота" этой проблемы не решит. Поэтому замена ключевых слов другими словами, но написанными кириллицей даже для учебных целей сомнительна. Более того, может быть даже вредна. Пока код написан "другими" буквами на "другом" языке, можно абстрагироваться от реального смысла слова float и оперировать тем смыслом, который это слово обозначает в коде, а не в нашем мире.

gbeam
17.10.2026 18:30@Честно говоря, не очень ясен практический смысл в этой "русификации".
Может, например, чтобы раскладку постоянно туда-сюда не переключать, в том случае если в коде много комментариев и текстовых строк на кириллице (как это сделано в 1C)?

artrades Автор
17.10.2026 18:30Проанализировав 9,14 миллиарда обсуждений на GitHub и более 62 500 патчей кода с 2015 по май 2025 года, мы показываем, что участие многоязычных пользователей неуклонно растет, особенно на корейском, китайском и русском языках.
...
Мы также обнаруживаем парадоксальную закономерность в разрешении проблем: проекты с преобладанием английского языка решают проблемы медленнее всего, в то время как неанглоязычные проекты делают это быстрее всего.
...

Popadanec
17.10.2026 18:30Создание программистов, которым будет сложнее уехать из страны.

randomsimplenumber
17.10.2026 18:30Не поможет. Он же, паршивец, все равно выучит бесовские if.

Serge78rus
17.10.2026 18:30Поможет. Если обучать на "суверенных языках программирования", то обучаемый скорее всего он еще в процессе обучения возненавидит программирование, а значит не станет программистом и никуда не уедет.

Blacpaul57
17.10.2026 18:30Опасность тут скорее в иллюзии простоты для начинающих. Человек заучивает русские ключевые слова, а потом открывает документацию к любому внешнему SDK и садится в лужу. Приходится переучиваться с нуля, проклиная добрых методистов

Popadanec
17.10.2026 18:30Я хоть и не программист, но понимаю что теория без практики мертва.

randomsimplenumber
17.10.2026 18:30Все равно придется смотреть документацию, примеры, тонны уже написанного кода. А там - упсь. if.

Blacpaul57
17.10.2026 18:30Смысл просто пет-проектный: поковырять AST компилятора и понять, как работает лексер на живом коде)

bio_bot
17.10.2026 18:30Я вот для себя нашел практический смысл в "руссификации" языков программирования. Если быть более точным, то для сына. Написали с ним свой DSL над Python, назвали это дело как полагается в честь нашего кота. Причесали все это иишаком не самым модным, и теперь ребенка не оторвать.
Суть не сделать из ребенка программиста, а просто научить думать алгоритмически. С чем моя подделка справляется на ура (для нас по крайней мере). Ребенку банально просто понимать все это дело в своей языковой среде. Но это мой частный случай.
Скорее всего вот такие вещи и будут решать задачи именно обучения.

Chemist_modeler
17.10.2026 18:30Друзья, не спешите минусовать автора! Мне тоже не очень нравится задача, всем понятно, почему она имеет шанс ноль целых ноль десятых на что-то практическое. Но автор честно написал, что не это для него главное.
Не всем дано стать мертвым страусом...Автору удачи в своих начинаниях и в выборе тем, а нам всем чуточку больше снисхождения к чужим хотелкам, даже если они нам не нравятся.

Serge78rus
17.10.2026 18:30В процессе подобных развлечений есть риск открыть ящик Пандоры, который потом будет очень трудно закрыть. Конечно, программисты - люди не глупые и сами разберутся, а вот попадание информации об "импортозамещенных языках программирования" в мозги какого-нибудь составителя программ школьного обучения может иметь очень печальные последствия.

randomsimplenumber
17.10.2026 18:30От Кумира еще никто не умер.

Serge78rus
17.10.2026 18:30От марксистко-ленинской философии тоже, во всяком случае прямо в процессе обучения, однако жалко потраченного времени. Причем это время потрачено в возрасте, когда мозг гораздо лучше усваивал информацию.

LimTroev
17.10.2026 18:30Ну да, пусть белорусы пишут на белорусском, китайцы на китайском, японцы на японском и т.д. Надо же как то хлебушек в эпоху ИИ теперь зарабатывать кому то. А то что универсальность теряется это ничего... Потом еще придумаем переводчик китайских программ на русские и т.п. Даешь изучение традиционно-ценностного РУСИ, РУГО, РУПИ, РУБЭ во всех образовательных учреждениях! ))))

RAprogramm
17.10.2026 18:30Дорогие друзья! Холивар это хорошо, но помогите лучше с реально полезной штукой - детерминированный языковой модуль для нашего великого словообразующего языка.
https://github.com/RAprogramm/rusem
Идея закодировать правила и логику языка

checkpoint
17.10.2026 18:30Эх, плохо что KPI программиста исчисляют в строках кода, а не в байтах. Так бы поможно было повысить производительность труда сразу в три раза! ;-)
А если серьезно, на опасную тропу Вы вышли с этим вот Вашим двояко-выпуклом языком. Соверешнно случайно эта статья может попасть на глаза какому нибудь чиновнуку из Минобрнауки и уже через год мы все тут начем говорить на двояком.

Serge78rus
17.10.2026 18:30Мы ладно - уже взрослые и сформировавшиеся. Трагедия будет для поколения, которому это начнут лить в уши еще со школы.

vadimr
17.10.2026 18:30В 80-90-е годы большинство школьников в СССР начинало изучать программирование с русскоязычных алгоритмического языка, Рапиры, Лого и т.п., и никакой трагедии в этом не было. Скорее полезно. Другое дело, что в Си вообще со словами напряг, и выглядит это уродливо.

Serge78rus
17.10.2026 18:30Аккуратней используйте слово "большинство". Мой сын как раз в конце 80-х - 90-х учился в школе. У них информатика преподавалась на турбо Паскале (естественно, ворованном). У детей друзей примерно в то же время было так же. Возможно, у кого-то и преподавали Рапиры, Лого и т.п., но точно не у большинства, либо это было уже позже означенного Вами периода.

vadimr
17.10.2026 18:30В конце 80-х Турбо Паскаль в школе мог появиться только благодаря редчайшему стечению обстоятельств, так как вообще IBM PC до 90-х был в СССР редкостью. Единый советский учебник информатики Ершова использовал русский алгоритмический язык, а большинство (действительно большинство) школьников в то время изучало программирование без компьютеров вообще. А если и были компьютеры в школах, то в основном до 1990 года отечественные или изредка болгарские.
Сам я начал изучать программирование в спецшколе с 7 класса с русского Лого. И очень завидовал школьникам, которые начинали со 2 класса с того же самого русского Лого. Понятно, что никакого английского языка второклассники в школах с техническим уклоном не знали.
Изучая программирование на очень продвинутом для школьника уровне, я IBM PC впервые увидел живьём в жизни в 1989 или 1990 году, а в учебном процессе (наряду с другими машинами) – в 1992 году в институте. (В тот период, кстати, я считал вычислительные машины, потребляющие меньше 100 кВт мощности, не очень достойными внимания – хотя я и начинал с персоналок).

Serge78rus
17.10.2026 18:30Боюсь ошибиться, но по моему у них было что-то типа Искры-1030 или ЕС-1840. Еще вспомнил, что примерно в то же время в школах было поделие под названием КУВТ (если не ошибся с аббревиатурой) - специальный учебный класс, по мотивам ДВК, БК-шки и т.д. Там в составе базового ПО был Бейсик.

apevzner
17.10.2026 18:30Гипотетически: каким бы был полноценный продакшеновый русский Си?
Ну, наверное, он не был бы продакшеновым :)

Daddy_Cool
17.10.2026 18:30Так вот ты какая, деглобализация!
Вашему вниманию предлагается классическая программа на языке С "Hello, wold!" на тамильском языке.
#உள்ளடக்கு <நிலையான உள்ளீட்டு/வெளியீட்டுத் தலைப்பு>முழுஎண் பிரதானசார்பு(வெறுமை)
{
அச்சிடு("வணக்கம், உலகமே\n");
திருப்பு 0;
}
-----------
По-моему это красиво...
А теперь серьезно. Интересно лингвистически-психологическая подоплека. Скажем в русифицированном Экселе ввод названий функций по-русски бесит. Вот с чем это связано... русский воспринимается как язык общения, и там могут быть многозначности, множественные смыслы, и т.п... а программирование это код, там лишние смыслы вредны.
Chemist_modeler
17.10.2026 18:30Меня тоже бесит русский эксель. Поэтому всегда ставлю только английский. Но - понять разработчиков можно: по-английски в нашей стране не сильно шпрехают даже преподаватели русского языка, не говоря об их учениках... Банально - будут хотя бы не путать букафки в названиях фукциев.

Wesha
17.10.2026 18:30по-английски в нашей стране не сильно шпрехают даже преподаватели русского языка
Так в том-то и хохма: читать код на ЯВУ как текст — это боль. Я вот языкеи всегда воспринимал как «этот „глиф“ означает цикл, этот — условие, этот — целое число» и тому подобное. Под словом «глиф» в данном случае понимается комбинация буковков (
while,if,int...) И тот факт что буковки латинские, помогало не читать слово, а воспринимать его как набор закорючек.

peschex0d
17.10.2026 18:30в русском экселе я просто не могу запомнить большинство названий функций, при этом и "цел" в Си для меня выглядит опечаткой, а код вида
цел й = ыкак кот прошёл по клавиатуре

trilirium
17.10.2026 18:30"நிலையான உள்ளீட்டு/வெளியீட்டுத் தலைப்பு" -- это "stdio.h"?
Почему так длинно? )))

sergeym69
17.10.2026 18:30"цел" это как то слишком кратко, лучше "целка"

Wesha
17.10.2026 18:30"цел" это как то слишком кратко, лучше "целка"
«Цел» — это когда выпал из окна второго этажа, отряхнулся и домой пошёл.

Elbrus128
17.10.2026 18:30Когда я хвалю российские разработки, то щирые и либерасты набегают и минусят карму, чтобы крамола на либеральном сайте не могла быть. Когда я ругаю бессмысленные проекты по русификации науки и техники, то набегают ура-патриоты и сносят карму. Никто не любит правды.
Русифицировать три десятка ключевых слов и 10 основных из них, требующихся при изучении программирования, нет смысла даже для младших школьников. Такие вещи запоминаются иероглифично — слово целиком для носителей любого языка. Просто, как один символ китайской грамоты, даже если китайского целиком не знаешь.
Более того, это полезно, т. к. несёт единственный смысл. У кого русский родной — понимает сразу и однозначно, что принтер — это периферийное устройство компьютера для получения аналоговой твëрдой копии документа.
У кого родной английский — уже возможны варианты...
В этом сила правила заимствования иностранных слов в русском языке.
Принтер — пример правильного и полезного заимствования. Лайфхак — пример мусорного и бесполезного заимствования.
P. S.: Можете понижать карму дальше. )) Если дискутировать это мне и не позволяет, то раз в неделю я всё равно могу писать вам сюда. )))

Chemist_modeler
17.10.2026 18:30Я в целом придерживаюсь Вашей логики, детали есть, но не суть. По существу Вас поддерживаю. А вот по форме не совсем. Чуток поболее уважения к коллегам, и, глядишь, минусить в карму перестанут.
Удачи!

Daddy_Cool
17.10.2026 18:30Уважения недостаточно. Чтобы получить минус в карму нужно всего лишь высказать мнение конфликтное на уровне ценностей. И как бы его вежливо ни высказал... ))) Конфликтные ценности делают человека врагом, потому что ценности потенциально определяют его действия.

randomsimplenumber
17.10.2026 18:30Лайфхак — пример мусорного и бесполезного заимствования.
Бесполезных заимствований не бывает. Раз словом пользуются - значит оно полезное

WLMike
17.10.2026 18:30Про Лайфхак очень сомнительно - мусорное умирает, в том числе изначально русские слова, полезное живет

saag
17.10.2026 18:30ну никак не устремление в будущее, все в прошлое, какие то if, если, надо иконку свечечки горящей, а вместо иначе иконка свечечки потухшей, дымящейся...

Roman_Cherkasov
17.10.2026 18:30Начал изучать программирование со школы, не зная английского языка вообще. Начал понятно с паскаля и учебников, которые давали в школе. Не шло. Было очень интересно но с тех пор терпеть не могу конструкции вроде - "Сделай так, получите это", без объяснений.
Потом стало интересно, на чем пишут "настоящие" программы. Мне учитель намекнул на C# и .net Framework. И выдал 2 диска. Один с Visual Studio и SDK, а второй с MSDN на русском. И вот нормальная документация на русском языке мне тогда помогла очень сильно. Да, у меня были названия классов и функций транслитом, но вот с ключевыми словами вообще не возникало проблем. Так что грамотно переведенный CPP Reference, разумеется, был бы сильно полезнее. Но на это, конечно, надо время потратить.

Riedl
17.10.2026 18:30Это полный бред, бредятина, фиаско. Не знаю откуда столько свободного времени взяли на эту чушь. Ладно бы какой то там ЦЕрковный Си++(ЦЕСИ++) или СОборный Си++ (СОСИ++)

Blacpaul57
17.10.2026 18:30Код на Си и без того перегружен макросами и указателями, а тут еще и русские синонимы вперемешку с английской libc. Если не переводить заголовки стандартной библиотеки, получается жуткая каша из printf и если. В итоге разработчик тратит половину сил не на логику, а на переключение контекста в голове

Tomasina
17.10.2026 18:30Нафига? Чтобы иной народ не смог разобраться в коде программы?
И да, сомневаюсь что такой код пройдет верификацию при регистрации ПО в реестре отечественного ПО.

randomsimplenumber
17.10.2026 18:30Чтобы иной народ не смог разобраться в коде программы?
Ллм в помощь.

trilirium
17.10.2026 18:30Переменная с именем "твёрдый знак" -- это же конь-цептуально!
Ради одного этого -- язык имело смысл создавать!! )))

virst
17.10.2026 18:30Мы уже видели до чедо довел фанатизм по поводу суверенного интернета. Суверенное программирование это шаг в туже сторону.

peschex0d
17.10.2026 18:30Программирование сильно опирается на reuse кода, а растаскивание кодовой базы по национальным норкам рушит переносимость (не это слово тут должно быть, но точное вряд ли подберу). Даже стандартный си с японскими, китайскими комментариями сложно читать, а уж с заменой ключевых слов национальными аналогами вдвойне.

Diacut
17.10.2026 18:30В очередной раз перепутали синтаксис с лексикой. Синтаксис си останется синтаксисом си, неважно "if" там или "если".
Бессмысленная работа.

peschex0d
17.10.2026 18:30На рубеже 2000 я пару лет вёл информатику в лицее и ФМШ на базе УКНЦ с Бейсиком и ibm pc с продуктами Борланд. Русифицированные среды в формате "черепашки" видел, но не использовал, поскольку plot/draw всё то же самое делает. У знакомых, связанных с системой образования, отношение к русскоязычным средам было от равнодушного до брезгливого, поскольку возможности совместной разработки, создания библиотек и больших проектов отсутствовали и все "черепашку" ощущали как обязательную пустую трату времени перед началом изучения Паскаля и си.
Десткий мозг гибкий и не зная языка, дети вполне считывают if else как логический блок, а не рассказ на английском, как и остальные ключевые слова. Ломать это восприятие, превращая программу в повесть, дикую смесь комментариев, отдельных букв в роли имени переменных и слов русского языка, которые наделены особыми правами в рамках синтаксиса, это насилие над разумом. Как пресловутое ВычСрЗнач в Экселе для бальзаковского возраста бухгалтерш, которые иное просто органически не осилят или не захотят.
На мой взгляд, от отделение семантики исходника от комментариев за счёт англоязычных ключевых слов это положительный фактор, увеличивающий и лаконичность кода и прозрачность его для носителей других языков. Си не был бы тем, чем он стал, без совместимости среди разработчиков разных стран, а в этом вопросе какой-то единый язык для написания операторов ключевой фактор.
Жаль, конечно, что не русский язык стал основным для MSDN, хехе, но причина явно не в отсутствии компилятора с "если" и "иначе".

vadimr
17.10.2026 18:30Всё-таки цель уроков информатики в школе – скорее воспитание логического и алгоритмического мышления в повседневной жизни, чем подготовка профессиональных программистов. И в этом плане любые отличия между языком программирования и естественным языком для школьников скорее вредны.
В детском курсе информатики не зря бывает много псевдокода для "программирования" людей. Зачем вводить искусственную разницу между черепашкой, которая понимает "DRAW", и соседом по парте, который понимает "НАРИСУЙ"?

randomsimplenumber
17.10.2026 18:30Зачем вводить искусственную разницу между черепашкой, которая понимает "DRAW", и соседом по парте, который понимает "НАРИСУЙ"?
Одно из них умеет понимать естественного языка, другое нет. Человеков программируют не так как роботов.

peschex0d
17.10.2026 18:30На развитии логики синтаксис не сказывается вообще никак.
При этом четверть века назад информатика в школе использовалась именно для воспроизводства программистов, учитывая CTR в 1% это не грозило их избытком )
Это позже мы расслабились, уверовали в то, что MS Office навсегда и давайте штамповать уверенных пользователей ПК.
Отличия между естественным языком и синтаксисом языка программирования обязаны быть, поскольку даже сейчас четверть века спустя программирование на естественном языке невозможно, либо требует гигантских ресурсов при сомнительном качестве сгенеренного кода. Нужно и правильно абстрагироваться от естественной речи, поскольку (и пока) компилятор придерживается конкретного синтаксиса.
В обсуждаемом форке gcc можно было бы добавить ещё условно полсотни синонимов для void как пример, но программист будет всё равно натыкаться на invalid keyword ошибки при попытке своими словами написать код и всё равно требуется знать подмножество естественного языка, которое применять можно.
Поэтому зачем плодить сущности?
Мне, кстати, наличие большего количества не англоязычных разработчиков кажется пруфом пользы от несовпадения ключевых слов с родным языком разработчика. Поскольку это чётко разграничивает логику, смысл и запись её символами.

vadimr
17.10.2026 18:30Информатику в школе учит каждый, а программистов мало. Даже из нашего программистского школьного класса (а мы изучали по специальной учебной программе именно программирование вдобавок к дисциплине всеобщего среднего образования – информатике) в итоге вышло два с половиной программиста. Так что, думаю, вероятностью обучить программиста на уроках информатики можно пренебречь, также как пренебрегают вероятностью обучить переводчика с арабского на уроках английского языка.

peschex0d
17.10.2026 18:30Мне кажется, вы из правильных исходных данных сделали неверный вывод. Я про это и писал выше, хорошо если 1% из обучающихся программистами станут, поскольку факторов необходимых больше одного.
Поэтому чтобы не остаться среди только пользователей, программированию нужно учить как можно более массово

peschex0d
17.10.2026 18:30Тут встречный вопрос, а когда и где тогда учить программистов, если не в школе. Раньше даже просто перерыв в учебе в ВУЗе на срочную службу воспринимали как потенциальный крах научной карьеры, поскольку вернувшись из армии многие шли работать и заводили семью.
С другой стороны, как в многих видах спорта, раннее обучение алгоритмизации даёт предпосылки продвинуться дальше. Поэтому в принципе такое обучение начинают в школе, а из старших классов сдвинули в начальную школу.
Сейчас, на фоне дефицита рабочих мест, я был бы рад отсутствию вообще обучения программированию в школах, но для страны и общества в целом это было бы губительно.

randomsimplenumber
17.10.2026 18:30страны и общества в целом это было бы губительно
Какая польза для общества от безработных программистов?
когда и где тогда учить программистов, если не в школе
После школы
Профессии раньше учили в ПТУ.

peschex0d
17.10.2026 18:30в ПТУ раньше шли отбросы, прошу прощения, неспособные осилить программу старших классов. Из них делать программистов, мне кажется, такое себе. Вот слесарей для АвтоВАЗа самое то.
сейчас в ПТУ выживают школьников ввиду экономии на ставках учителей старших классов и это работает иначе, чем тогда.
Какая польза для общества от безработных программистов?
от любых безработных есть польза стартапам при найме соответствующих специалистов, хоть сварщиков, хоть юристов.
при этом я не считаю адептов секты Назарова (вкатунов в айтишечку) программистами и поэтому не считаю их безработицу чем-то неправильным.
но эмпирически мы выяснили, что процент работающих программистами сильно ниже, чем толпа формально прошедших обучение основам алогритмизации и бейсику, например
и это меня наводит на мысль, что при фиксированном проценте выхлопа если мы хотим избежать кадрового голода, надо просто пытаться обучить больше программистов
никого же не шокирует, что в школе дети ходят на лыжах на физкультуре и плавают в бассейне, а членами олимпийской сборной становятся не каждый даже сотый школьник.
или шокирует?
После школы
Профессии раньше учили в ПТУ
Я согласен с тем, когда плотника или слесаря учат в ПТУ, потому что для ряда профессий ученик банально должен обладать физической силой и мозгами, чтобы например не тыкать электродом сварочного аппарата себе в глаз.
при этом логическое мышление развивается тем успешнее, чем раньше начато развитие и условно возраст 6-7 лет для начала информатики - самое то, чтобы ребенка не перегружать и более сложные вещи он успел осилить до условно периода "год топтания плаца сапогами"
а в вузе знакния по специальности (если это не узко программирование) легли бы на хороший базовый навык написания кода, а не пришлось осиливать понятие переменной с нуля.
у меня лично информатики в школе не было, перфокарты, СМ4 и ДВК я увидел впервые учась в вузе, БК0010 и его ассемблер осваивал дома примерно в те же годы, но будь у меня лет пять запаса времени, то есть, начни я ковыряться еще в школе, скорее всего был бы только рад.

randomsimplenumber
17.10.2026 18:30Прикиньте, вам в школе прогать было интересно. А остальным? Конечно, китайский метод - пусть учат все, из миллиона выберем 10 способных - хорош, если есть в запасе 1 000 000 000 китайцев.
Программирование - рабочая профессия. В ПТУ ей нормально. Только ПТУ не для сварщиков а для программистов.

the_homeless_god
17.10.2026 18:30Вообще писал недавно о решении, с любой семантикой тут https://habr.com/ru/articles/1095038/
Для нетерпеливых https://github.com/digitable-lol/flang

DmitrySolomennikov
17.10.2026 18:30Просто оставлю это здесь
https://github.com/andrey-terekhov/RuC
Разработка Андрея Николаевича Терехова

igorek_tm
17.10.2026 18:30есть конструктивная мысль: Т.к. основная проблема (мне) видится в размерах русских аналогов названий операторов - сравним "if" и "если" - двукратное увеличение слова, какой ужас начнется с switch - case, или конструкциями типа exception просто не хочется и думать. А если использовать обсценную лексику? Такого рода слова гораздо короче и в силу некоторой неопределенности значения могли бы быть использованы в "русском Си". Длинные слова-операторы continue, return, break а то и goto (!!) прекрасно заменились бы гораздо более короткими, причем читаемость кода, на мой взгляд, только улучшилась бы.

randomsimplenumber
17.10.2026 18:30А если использовать обсценную лексику?
-- Плохой человек?
-- редиска
-- unsigned long long int ?
-- забыл..

perebour
17.10.2026 18:30Кто пустил одинэсника в тред?
Ужасная скреподуховная импортозамешенная суверенная мешанина на месте того, что признано международным стандартом

Desvor
17.10.2026 18:30Ни в коем случае не хочу обидеть автора, сли он писал это сам, но что-то мне напоминает текст ИИшный. Это не плохо, но мне интересно: у меня шиза, или есть место быть?


Kotofay
https://habr.com/ru/articles/1003246/comments/#comment_29579650
randomsimplenumber
Так проще ;)
Yukr
"Ключница синтаксис делала.."(с)
Chemist_modeler
Ну да, только с первой "Г".
Kotofay
.
artrades Автор
Дефайны не интересно
randomsimplenumber
Если нет разницы.. (ц)
trinxery
Утянуто из https://habr.com/ru/articles/41561/
qngdjas
Кто ещё пропел?