762 lines
41 KiB
Markdown
762 lines
41 KiB
Markdown
|
|
```markdown
|
|||
|
|
# Руси: двуязычный компилятор C с русским синтаксисом
|
|||
|
|
|
|||
|
|
**Руси** — это компилятор языка C, поддерживающий **полноценный двуязычный синтаксис**.
|
|||
|
|
Вы можете писать программы на C, используя как **английские**, так и **русские** ключевые слова, типы данных, операторы и директивы препроцессора — в любом сочетании, в одном файле.
|
|||
|
|
|
|||
|
|
Название проекта — **Руси** — говорит само за себя: это язык C, заговоривший по-русски, но при этом сохранивший родной английский синтаксис для тех, кому он привычнее.
|
|||
|
|
|
|||
|
|
Проект вдохновлен двумя реализациями:
|
|||
|
|
- [chibicc](https://github.com/rui314/chibicc) — небольшой, но мощный C11 компилятор, способный компилировать реальные проекты.(Собственно и сделан на его основе)
|
|||
|
|
- [c89cc.sh](https://gist.github.com/alganet/2b89c4368f8d23d033961d8a3deb5c19) — минималистичный компилятор C89/ELF64 на чистом shell, демонстрирующий невероятную простоту реализации.
|
|||
|
|
|
|||
|
|
Проект **Руси** разработан для портирования компилятора [КВС (kvs)](https://github.com/artradeskz/kvs) — ассемблера с русским синтаксисом, написанного на Python. Вместо того чтобы использовать интерпретатор Python для сборки, **Руси** позволит скомпилировать этот ассемблер в нативный бинарный файл, значительно повысив производительность и удобство использования.
|
|||
|
|
|
|||
|
|
## Двуязычность: как это работает
|
|||
|
|
|
|||
|
|
**Руси** одновременно понимает два языка: английский C и русский C. Это означает, что:
|
|||
|
|
|
|||
|
|
- Вы можете писать код **полностью на английском** — как в любом стандартном C.
|
|||
|
|
- Вы можете писать код **полностью на русском** — используя русские ключевые слова, типы и операторы.
|
|||
|
|
- Вы можете **смешивать** английский и русский синтаксис в одном файле.
|
|||
|
|
|
|||
|
|
Это делает компилятор идеальным инструментом для обучения, миграции проектов и команд с разными языковыми предпочтениями.
|
|||
|
|
|
|||
|
|
### Примеры смешанного синтаксиса
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// Английский main с русским типом и оператором
|
|||
|
|
int главн() {
|
|||
|
|
цел x = 42;
|
|||
|
|
if (x == 42) {
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Русский
|
|||
|
|
цел главн() {
|
|||
|
|
цел ы = 42;
|
|||
|
|
если (ы == 42) {
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
возврат 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Полностью смешанный стиль
|
|||
|
|
цел main() {
|
|||
|
|
int счетчик = 0;
|
|||
|
|
для (счетчик = 0; счетчик < 10; счетчик = счетчик + 1) {
|
|||
|
|
if (счетчик % 2 == 0) {
|
|||
|
|
printf("Четное: %d\n", счетчик);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Полный список русских слов для программирования
|
|||
|
|
|
|||
|
|
### Типы данных (13)
|
|||
|
|
|
|||
|
|
| Английский | Русский | Пример |
|
|||
|
|
|------------|---------|--------|
|
|||
|
|
| `int` | `цел` | `цел x = 42;` |
|
|||
|
|
| `char` | `символ` | `символ c = 'A';` |
|
|||
|
|
| `short` | `корот` | `корот s = 123;` |
|
|||
|
|
| `long` | `длин` | `длин l = 456789;` |
|
|||
|
|
| `void` | `пусто` | `пусто функция() {}` |
|
|||
|
|
| `float` | `плав` | `плав f = 3.14;` |
|
|||
|
|
| `double` | `двойн` | `двойн d = 2.71;` |
|
|||
|
|
| `struct` | `структ` | `структ Точка {};` |
|
|||
|
|
| `union` | `объед` | `объед Данные {};` |
|
|||
|
|
| `enum` | `переч` | `переч Цвет {};` |
|
|||
|
|
| `_Bool` | `бул` | `бул flag = истина;` |
|
|||
|
|
| `unsigned` | `беззнак` | `беззнак цел u = 42;` |
|
|||
|
|
| `signed` | `знак` | `знак цел s = -42;` |
|
|||
|
|
|
|||
|
|
### Ключевые слова (16)
|
|||
|
|
|
|||
|
|
| Английский | Русский | Пример |
|
|||
|
|
|------------|---------|--------|
|
|||
|
|
| `typedef` | `типдеф` | `типдеф цел МойЦел;` |
|
|||
|
|
| `static` | `стат` | `стат цел счетчик = 0;` |
|
|||
|
|
| `extern` | `внеш` | `внеш цел глобальная;` |
|
|||
|
|
| `inline` | `инлайн` | `инлайн цел квадрат() {}` |
|
|||
|
|
| `const` | `конст` | `конст цел x = 42;` |
|
|||
|
|
| `volatile` | `летуч` | `летуч цел x;` |
|
|||
|
|
| `auto` | `авто` | `авто цел x = 42;` |
|
|||
|
|
| `register` | `регистр` | `регистр цел x;` |
|
|||
|
|
| `restrict` | `огранич` | `цел * огранич ptr;` |
|
|||
|
|
| `_Alignas` | `_Выравнивание` | `_Выравнивание(16) символ buf[32];` |
|
|||
|
|
| `_Alignof` | `_Выравнивание_типа` | `_Выравнивание_типа(цел);` |
|
|||
|
|
| `_Noreturn` | `_Безвозврат` | `_Безвозврат пусто функция() {}` |
|
|||
|
|
| `_Generic` | `_Обобщ` | `_Обобщ(42, цел: 1, умолч: 0);` |
|
|||
|
|
| `_Atomic` | `_Атом` | `_Атом цел x;` |
|
|||
|
|
| `_Thread_local` | `_Поток_лок` | `_Поток_лок цел x;` |
|
|||
|
|
| `__thread` | `__поток` | `__поток цел x;` |
|
|||
|
|
|
|||
|
|
### Операторы (18)
|
|||
|
|
|
|||
|
|
| Английский | Русский | Пример |
|
|||
|
|
|------------|---------|--------|
|
|||
|
|
| `return` | `возврат` | `возврат 0;` |
|
|||
|
|
| `if` | `если` | `если (x == 10) {}` |
|
|||
|
|
| `else` | `иначе` | `иначе {}` |
|
|||
|
|
| `for` | `для` | `для (i = 0; i < 10; i++) {}` |
|
|||
|
|
| `while` | `пока` | `пока (i < 10) {}` |
|
|||
|
|
| `do` | `делай` | `делай {} пока (i < 10);` |
|
|||
|
|
| `switch` | `выбор` | `выбор (x) {}` |
|
|||
|
|
| `case` | `случай` | `случай 1:` |
|
|||
|
|
| `default` | `умолч` | `умолч:` |
|
|||
|
|
| `goto` | `перейти` | `перейти метка;` |
|
|||
|
|
| `break` | `прерви` | `прерви;` |
|
|||
|
|
| `continue` | `продолжи` | `продолжи;` |
|
|||
|
|
| `sizeof` | `размер` | `размер(цел);` |
|
|||
|
|
| `typeof` | `типоф` | `типоф(x) y;` |
|
|||
|
|
| `asm` | `асм` | `асм("nop");` |
|
|||
|
|
| `&&` | Оставлено как есть | `x && y` |
|
|||
|
|
| `\|\|` | Оставлено как есть | `x \|\| y` |
|
|||
|
|
| `!` | Оставлено как есть | `!x` |
|
|||
|
|
|
|||
|
|
### Директивы препроцессора (15)
|
|||
|
|
|
|||
|
|
| Английский | Русский | Пример |
|
|||
|
|
|------------|---------|--------|
|
|||
|
|
| `#include` | `#включить` | `#включить <stdio.h>` |
|
|||
|
|
| `#include_next` | `#включить_след` | `#включить_след "file.h"` |
|
|||
|
|
| `#define` | `#определить` | `#определить ПИ 3.14` |
|
|||
|
|
| `#undef` | `#отменить` | `#отменить ПИ` |
|
|||
|
|
| `#if` | `#если` | `#если ВЕРСИЯ == 2` |
|
|||
|
|
| `#ifdef` | `#еслиопр` | `#еслиопр ТЕСТ` |
|
|||
|
|
| `#ifndef` | `#еслинеопр` | `#еслинеопр ТЕСТ` |
|
|||
|
|
| `#elif` | `#иначеесли` | `#иначеесли ВЕРСИЯ == 2` |
|
|||
|
|
| `#else` | `#иначе` | `#иначе` |
|
|||
|
|
| `#endif` | `#конецесли` | `#конецесли` |
|
|||
|
|
| `#line` | `#строка` | `#строка 100 "file.c"` |
|
|||
|
|
| `#error` | `#ошибка` | `#ошибка "Сообщение"` |
|
|||
|
|
| `#pragma` | `#прагма` | `#прагма once` |
|
|||
|
|
| `defined` | `определено` | `#если определено(ТЕСТ)` |
|
|||
|
|
| `once` | `однократно` | `#прагма однократно` |
|
|||
|
|
|
|||
|
|
### Встроенные макросы (9)
|
|||
|
|
|
|||
|
|
| Английский | Русский | Пример |
|
|||
|
|
|------------|---------|--------|
|
|||
|
|
| `__FILE__` | `__ФАЙЛ__` | `символ *f = __ФАЙЛ__;` |
|
|||
|
|
| `__LINE__` | `__ЛИНИЯ__` | `цел n = __ЛИНИЯ__;` |
|
|||
|
|
| `__func__` | `__функ__` | `символ *f = __функ__;` |
|
|||
|
|
| `__FUNCTION__` | `__ФУНКЦИЯ__` | `символ *f = __ФУНКЦИЯ__;` |
|
|||
|
|
| `__COUNTER__` | `__СЧЕТЧИК__` | `цел n = __СЧЕТЧИК__;` |
|
|||
|
|
| `__TIMESTAMP__` | `__ВРЕМЯ_ФАЙЛА__` | `символ *t = __ВРЕМЯ_ФАЙЛА__;` |
|
|||
|
|
| `__DATE__` | `__ДАТА__` | `символ *d = __ДАТА__;` |
|
|||
|
|
| `__TIME__` | `__ВРЕМЯ__` | `символ *t = __ВРЕМЯ__;` |
|
|||
|
|
| `__BASE_FILE__` | `__БАЗОВЫЙ_ФАЙЛ__` | `символ *b = __БАЗОВЫЙ_ФАЙЛ__;` |
|
|||
|
|
|
|||
|
|
### Функции (1)
|
|||
|
|
|
|||
|
|
| Английский | Русский | Пример |
|
|||
|
|
|------------|---------|--------|
|
|||
|
|
| `main` | `главн` | `цел главн() {}` |
|
|||
|
|
|
|||
|
|
## Особенности
|
|||
|
|
|
|||
|
|
- **Двуязычный синтаксис**: все ключевые слова, типы, операторы и директивы препроцессора доступны как на английском, так и на русском языке.
|
|||
|
|
- **Смешивание языков**: английский и русский синтаксис можно использовать в одном файле в любых сочетаниях.
|
|||
|
|
- **Русские идентификаторы**: можно называть переменные, функции и структуры по-русски.
|
|||
|
|
- **Русские имена файлов и расширения**: компилятор работает с файлами `программа.си` и заголовками `привет.з`.
|
|||
|
|
- **Полная поддержка C11**: включая препроцессор, битовые поля, VLA, атомарные и thread-local переменные.
|
|||
|
|
- **70+ переведенных конструкций**: все ключевые слова, операторы, макросы и директивы покрыты тестами.
|
|||
|
|
|
|||
|
|
## Пример программы (смешанный синтаксис)
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
#включить <stdio.h>
|
|||
|
|
#включить <stdbool.h>
|
|||
|
|
|
|||
|
|
структ Точка {
|
|||
|
|
цел x;
|
|||
|
|
цел y;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
цел сумма_координат(структ Точка точка) {
|
|||
|
|
возврат точка.x + точка.y;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
цел главн() {
|
|||
|
|
цел массив[10];
|
|||
|
|
for (цел i = 0; i < 10; i = i + 1) {
|
|||
|
|
массив[i] = i * 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int сумма = 0;
|
|||
|
|
для (int i = 0; i < 10; i = i + 1) {
|
|||
|
|
сумма = сумма + массив[i];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
если (sum == 90) {
|
|||
|
|
printf("Сумма: %d\n", сумма);
|
|||
|
|
} else {
|
|||
|
|
printf("Ошибка!\n");
|
|||
|
|
возврат 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
struct Точка точка = {10, 20};
|
|||
|
|
цел результат = сумма_координат(точка);
|
|||
|
|
|
|||
|
|
если (результат == 30) {
|
|||
|
|
printf("OK\n");
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Импорт файлов с русскими именами
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// привет.з - русский заголовочный файл
|
|||
|
|
#еслинеопр ПРИВЕТ_З
|
|||
|
|
#определить ПРИВЕТ_З
|
|||
|
|
|
|||
|
|
#включить <stdio.h>
|
|||
|
|
#define ПЕЧАТЬ printf
|
|||
|
|
|
|||
|
|
#endif
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// программа.рс - основная программа
|
|||
|
|
#включить "привет.з"
|
|||
|
|
|
|||
|
|
цел главн() {
|
|||
|
|
ПЕЧАТЬ("Привет, мир!\n");
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Компиляция русских файлов
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./руси программа.рс -o программа
|
|||
|
|
./программа
|
|||
|
|
# Вывод: Привет, мир!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Внутреннее устройство
|
|||
|
|
|
|||
|
|
Компилятор состоит из четырех этапов:
|
|||
|
|
1. **Токенизация** — разбиение исходного кода на токены (с поддержкой UTF-8 и кириллицы).
|
|||
|
|
2. **Препроцессинг** — обработка директив и макросов (с русскими синонимами).
|
|||
|
|
3. **Парсинг** — построение AST с использованием рекурсивного спуска.
|
|||
|
|
4. **Генерация кода** — создание ассемблерного текста для x86-64 (ELF64).
|
|||
|
|
|
|||
|
|
## Тестирование и самосборка
|
|||
|
|
|
|||
|
|
Проект имеет две независимые системы тестирования:
|
|||
|
|
|
|||
|
|
### 1. Стандартные тесты (английский синтаксис)
|
|||
|
|
|
|||
|
|
Запускаются командой `make test`. Проверяют базовую функциональность компилятора на оригинальном C.
|
|||
|
|
|
|||
|
|
### 2. Русские тесты
|
|||
|
|
|
|||
|
|
Запускаются командой `make test-ru`. Написаны на Python (`test_ru/run_tests.py`) и проверяют все русские синонимы. 70+ тестов покрывают все переведенные конструкции:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
make test-ru
|
|||
|
|
# Вывод: 🎉 Все тесты пройдены!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Самосборка (Stage 2)
|
|||
|
|
|
|||
|
|
Компилятор способен скомпилировать сам себя. Этот процесс называется **самосборкой** (self-hosting) и подтверждает, что компилятор достаточно зрелый для работы с собственным кодом.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
make test-stage2
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Эта команда:
|
|||
|
|
1. Компилирует компилятор с помощью самого себя (stage2)
|
|||
|
|
2. Проверяет, что stage2-версия проходит все тесты
|
|||
|
|
3. Подтверждает, что компилятор способен воспроизвести себя
|
|||
|
|
|
|||
|
|
Самосборка — важный этап разработки компилятора, доказывающий его надежность и полноту.
|
|||
|
|
|
|||
|
|
## Планы по миграции исходного кода на русский синтаксис
|
|||
|
|
|
|||
|
|
Текущая версия компилятора уже **полностью понимает русский синтаксис** и успешно проходит все тесты (включая 70+ русских тестов). Следующий логический шаг — **переписать сам исходный код компилятора на русском синтаксисе**.
|
|||
|
|
|
|||
|
|
### Что это даст?
|
|||
|
|
|
|||
|
|
1. **Полная русификация**: исходный код компилятора будет написан на том же языке, который он компилирует.
|
|||
|
|
2. **Демонстрация возможностей**: сам компилятор станет лучшим примером использования русского синтаксиса.
|
|||
|
|
3. **Образовательная ценность**: русскоязычные студенты смогут изучать устройство компилятора без языкового барьера.
|
|||
|
|
4. **Двуязычная кодовая база**: английская и русская версии будут существовать параллельно.
|
|||
|
|
|
|||
|
|
### Как это будет сделано
|
|||
|
|
|
|||
|
|
1. **Поэтапная миграция**: исходный код будет переписан на русский синтаксис постепенно, файл за файлом.
|
|||
|
|
2. **Сохранение двуязычности**: компилятор продолжит понимать оба синтаксиса.
|
|||
|
|
3. **Тестирование**: после каждого этапа будет запускаться полный набор тестов.
|
|||
|
|
4. **Самосборка**: после завершения миграции компилятор сможет скомпилировать себя из русскоязычного исходного кода.
|
|||
|
|
|
|||
|
|
### Статус
|
|||
|
|
|
|||
|
|
- ✅ **Компилятор понимает русский синтаксис** — полностью готово.
|
|||
|
|
- ✅ **Функция main переименована в главн** — сделано.
|
|||
|
|
- ⏳ **Миграция исходного кода на русский синтаксис** — в планах.
|
|||
|
|
- ⏳ **Самосборка из русскоязычного исходного кода** — следующий этап.
|
|||
|
|
|
|||
|
|
### Пример того, как будет выглядеть код компилятора на русском
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// Токенизатор на русском синтаксисе (планируется)
|
|||
|
|
структ Токен {
|
|||
|
|
переч ВидТокена вид;
|
|||
|
|
Токен *следующий;
|
|||
|
|
цел значение;
|
|||
|
|
символ *позиция;
|
|||
|
|
цел длина;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
цел прочитать_идентификатор(символ *начало) {
|
|||
|
|
символ *p = начало;
|
|||
|
|
цел c = декодировать_utf8(&p, p);
|
|||
|
|
если (!это_идентификатор1(c)) {
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
пока (истина) {
|
|||
|
|
символ *q;
|
|||
|
|
c = декодировать_utf8(&q, p);
|
|||
|
|
если (!это_идентификатор2(c)) {
|
|||
|
|
возврат p - начало;
|
|||
|
|
}
|
|||
|
|
p = q;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Портирование КВС (kvs) с Python на C
|
|||
|
|
|
|||
|
|
Проект **Руси** разработан с прицелом на портирование компилятора [КВС (kvs)](https://github.com/artradeskz/kvs) — ассемблера с русским синтаксисом для x86-64, написанного на Python.
|
|||
|
|
|
|||
|
|
### Зачем это нужно?
|
|||
|
|
|
|||
|
|
КВС (расшифровывается как "Код В Силу" или просто "КВС") — это образовательный ассемблер, который использует русскую лексику для мнемоник инструкций, имён регистров и директив. Однако он написан на Python и работает как интерпретатор, что ограничивает его производительность и распространение.
|
|||
|
|
|
|||
|
|
**Руси** позволит:
|
|||
|
|
|
|||
|
|
1. **Скомпилировать КВС в нативный бинарный файл** — вместо интерпретации Python-скриптов, ассемблер будет работать как обычный исполняемый файл.
|
|||
|
|
2. **Значительно повысить производительность** — компилированный код работает на порядок быстрее интерпретируемого.
|
|||
|
|
3. **Распространять как самостоятельный бинарник** — не требуется устанавливать Python и зависимости.
|
|||
|
|
4. **Улучшить интеграцию** — бинарный файл легче встраивать в различные системы и инструменты.
|
|||
|
|
|
|||
|
|
### Как будет происходить портирование
|
|||
|
|
|
|||
|
|
1. **Анализ архитектуры КВС**: КВС состоит из шести проходов: лексер, парсер, 4 прохода разрешения меток и констант, финальная сборка ELF.
|
|||
|
|
2. **Переписывание на C с русским синтаксисом**: каждый модуль будет переписан на C, используя русские ключевые слова и идентификаторы.
|
|||
|
|
3. **Сохранение логики**: шестипроходная архитектура останется, но будет оптимизирована для нативного выполнения.
|
|||
|
|
4. **Полная совместимость**: бинарный файл должен компилировать те же `.квс` файлы, что и оригинальный Python-скрипт.
|
|||
|
|
|
|||
|
|
### Пример: лексер КВС на русском C
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// планируемый код лексера КВС на русском C
|
|||
|
|
структ Токен {
|
|||
|
|
переч ВидТокена вид;
|
|||
|
|
символ *текст;
|
|||
|
|
цел длина;
|
|||
|
|
Токен *следующий;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Токен *лексический_анализ(символ *исходник) {
|
|||
|
|
Токен *голова = нуль;
|
|||
|
|
Токен *текущий = нуль;
|
|||
|
|
символ *позиция = исходник;
|
|||
|
|
|
|||
|
|
пока (*позиция != '\0') {
|
|||
|
|
пропустить_пробелы(&позиция);
|
|||
|
|
если (*позиция == '\0') {
|
|||
|
|
прерви;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
если (*позиция == ';') {
|
|||
|
|
пропустить_комментарий(&позиция);
|
|||
|
|
продолжи;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Токен *токен = выделить_токен(&позиция);
|
|||
|
|
если (голова == нуль) {
|
|||
|
|
голова = токен;
|
|||
|
|
} иначе {
|
|||
|
|
текущий->следующий = токен;
|
|||
|
|
}
|
|||
|
|
текущий = токен;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
возврат голова;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Преимущества портирования для КВС
|
|||
|
|
|
|||
|
|
| Аспект | Python-версия (оригинал) | C-версия (план) |
|
|||
|
|
|--------|--------------------------|-----------------|
|
|||
|
|
| **Скорость сборки** | ~0.5-1.0 сек для простых программ | ~0.01-0.05 сек |
|
|||
|
|
| **Установка** | Требуется Python 3.7+ | Ничего не требуется |
|
|||
|
|
| **Распространение** | Исходники или .deb | Один бинарник |
|
|||
|
|
| **Зависимости** | Стандартная библиотека Python | Только libc |
|
|||
|
|
| **Интеграция** | Только как скрипт | Может встраиваться в любую систему |
|
|||
|
|
|
|||
|
|
### План работ по портированию
|
|||
|
|
|
|||
|
|
1. **Этап 1**: Портирование лексера (`квс_лексер.py` → `лексер.рс`)
|
|||
|
|
2. **Этап 2**: Портирование парсера (`квс_парсер.py` → `парсер.рс`)
|
|||
|
|
3. **Этап 3**: Портирование четырех проходов (`квс_проход*.py` → `проход*.рс`)
|
|||
|
|
4. **Этап 4**: Портирование финальной сборки ELF (`квс_финсбор.py` → `финсбор.рс`)
|
|||
|
|
5. **Этап 5**: Интеграция в единый бинарник (`квс_сборка.рс`)
|
|||
|
|
6. **Этап 6**: Тестирование на всех 26 тестах КВС
|
|||
|
|
|
|||
|
|
## Подсветка синтаксиса для VS Code / VS Codium
|
|||
|
|
|
|||
|
|
В планах разработка **расширения для подсветки синтаксиса** русского C для редакторов VS Code и VS Codium.
|
|||
|
|
|
|||
|
|
### Что будет поддерживаться
|
|||
|
|
|
|||
|
|
- **Русские ключевые слова**: подсветка всех переведенных конструкций (`цел`, `если`, `возврат` и др.)
|
|||
|
|
- **Русские идентификаторы**: правильное распознавание переменных и функций с кириллицей
|
|||
|
|
- **Русские директивы препроцессора**: подсветка `#включить`, `#определить` и др.
|
|||
|
|
- **Русские имена файлов**: корректная работа с файлами `.рс` и `.з`
|
|||
|
|
|
|||
|
|
### Планируемые функции расширения
|
|||
|
|
|
|||
|
|
- **Автодополнение**: подсказки для русских ключевых слов
|
|||
|
|
- **Фрагменты кода**: готовые шаблоны для `если`, `для`, `структ` и др.
|
|||
|
|
- **Форматирование**: автоматическое форматирование кода с русским синтаксисом
|
|||
|
|
- **Проверка синтаксиса**: интеграция с компилятором **Руси** для проверки ошибок
|
|||
|
|
|
|||
|
|
### Статус
|
|||
|
|
|
|||
|
|
- ⏳ **Разработка расширения для подсветки синтаксиса** — в планах.
|
|||
|
|
- ⏳ **Интеграция с компилятором** — следующий этап.
|
|||
|
|
|
|||
|
|
## Планы по русификации стандартной библиотеки
|
|||
|
|
|
|||
|
|
В планах создание **русскоязычной стандартной библиотеки** — заголовочных файлов с русскими именами для всех основных функций и констант.
|
|||
|
|
|
|||
|
|
### Зачем это нужно?
|
|||
|
|
|
|||
|
|
Русификация стандартной библиотеки сделает русский синтаксис по-настоящему завершенным. Программист сможет не только писать ключевые слова на русском, но и использовать функции и константы с русскими именами:
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
#включить <стандарт.з>
|
|||
|
|
|
|||
|
|
цел главн() {
|
|||
|
|
// Вместо printf("Привет!\n");
|
|||
|
|
печать("Привет!\n");
|
|||
|
|
|
|||
|
|
// Вместо strlen("текст");
|
|||
|
|
цел длина = длина_строки("текст");
|
|||
|
|
|
|||
|
|
// Вместо malloc(100);
|
|||
|
|
пусто *память = выделить(100);
|
|||
|
|
|
|||
|
|
// Вместо free(память);
|
|||
|
|
освободить(память);
|
|||
|
|
|
|||
|
|
возврат 0;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Какие функции будут переведены
|
|||
|
|
|
|||
|
|
| Английское имя | Русское имя | Заголовочный файл |
|
|||
|
|
|----------------|-------------|-------------------|
|
|||
|
|
| `printf` | `печать` | `стандарт.з` (stdio.h) |
|
|||
|
|
| `scanf` | `ввод` | `стандарт.з` (stdio.h) |
|
|||
|
|
| `puts` | `вывод_строки` | `стандарт.з` (stdio.h) |
|
|||
|
|
| `gets` | `получить_строку` | `стандарт.з` (stdio.h) |
|
|||
|
|
| `malloc` | `выделить` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `free` | `освободить` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `calloc` | `выделить_нули` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `realloc` | `перевыделить` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `strlen` | `длина_строки` | `строки.з` (string.h) |
|
|||
|
|
| `strcpy` | `копировать_строку` | `строки.з` (string.h) |
|
|||
|
|
| `strcmp` | `сравнить_строки` | `строки.з` (string.h) |
|
|||
|
|
| `strcat` | `склеить_строки` | `строки.з` (string.h) |
|
|||
|
|
| `strchr` | `найти_в_строке` | `строки.з` (string.h) |
|
|||
|
|
| `strstr` | `найти_подстроку` | `строки.з` (string.h) |
|
|||
|
|
| `memcpy` | `копировать_память` | `память.з` (string.h) |
|
|||
|
|
| `memset` | `заполнить_память` | `память.з` (string.h) |
|
|||
|
|
| `memcmp` | `сравнить_память` | `память.з` (string.h) |
|
|||
|
|
| `exit` | `завершить` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `rand` | `случайное` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `srand` | `инициализировать_случайное` | `стандарт.з` (stdlib.h) |
|
|||
|
|
| `time` | `время` | `время.з` (time.h) |
|
|||
|
|
| `sqrt` | `корень` | `математика.з` (math.h) |
|
|||
|
|
| `sin` | `синус` | `математика.з` (math.h) |
|
|||
|
|
| `cos` | `косинус` | `математика.з` (math.h) |
|
|||
|
|
| `tan` | `тангенс` | `математика.з` (math.h) |
|
|||
|
|
| `pow` | `степень` | `математика.з` (math.h) |
|
|||
|
|
| `abs` | `модуль` | `стандарт.з` (stdlib.h) |
|
|||
|
|
|
|||
|
|
### Как это будет реализовано
|
|||
|
|
|
|||
|
|
1. **Создание заголовочных файлов с русскими именами**: например, `стандарт.з` (аналог stdio.h + stdlib.h), `строки.з` (string.h), `математика.з` (math.h).
|
|||
|
|
2. **Использование макросов**: русские имена будут определены через `#define` или через `typedef`.
|
|||
|
|
3. **Полная совместимость**: можно будет использовать как русские, так и английские имена в одной программе.
|
|||
|
|
|
|||
|
|
### Пример заголовочного файла `стандарт.з`
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// стандарт.з - русская стандартная библиотека
|
|||
|
|
#еслинеопр СТАНДАРТ_З
|
|||
|
|
#определить СТАНДАРТ_З
|
|||
|
|
|
|||
|
|
#включить <stdio.h>
|
|||
|
|
#включить <stdlib.h>
|
|||
|
|
#включить <string.h>
|
|||
|
|
#включить <math.h>
|
|||
|
|
|
|||
|
|
// Ввод-вывод
|
|||
|
|
#определить печать printf
|
|||
|
|
#определить ввод scanf
|
|||
|
|
#определить вывод_строки puts
|
|||
|
|
#определить получить_строку gets
|
|||
|
|
#определить вывод_ошибки fprintf
|
|||
|
|
|
|||
|
|
// Управление памятью
|
|||
|
|
#определить выделить malloc
|
|||
|
|
#определить освободить free
|
|||
|
|
#определить выделить_нули calloc
|
|||
|
|
#определить перевыделить realloc
|
|||
|
|
|
|||
|
|
// Завершение программы
|
|||
|
|
#определить завершить exit
|
|||
|
|
|
|||
|
|
// Работа со строками
|
|||
|
|
#определить длина_строки strlen
|
|||
|
|
#определить копировать_строку strcpy
|
|||
|
|
#определить сравнить_строки strcmp
|
|||
|
|
#определить склеить_строки strcat
|
|||
|
|
#определить найти_в_строке strchr
|
|||
|
|
#определить найти_подстроку strstr
|
|||
|
|
|
|||
|
|
// Работа с памятью
|
|||
|
|
#определить копировать_память memcpy
|
|||
|
|
#определить заполнить_память memset
|
|||
|
|
#определить сравнить_память memcmp
|
|||
|
|
|
|||
|
|
// Случайные числа
|
|||
|
|
#определить случайное rand
|
|||
|
|
#определить инициализировать_случайное srand
|
|||
|
|
|
|||
|
|
// Математика
|
|||
|
|
#определить корень sqrt
|
|||
|
|
#определить синус sin
|
|||
|
|
#определить косинус cos
|
|||
|
|
#определить тангенс tan
|
|||
|
|
#определить степень pow
|
|||
|
|
|
|||
|
|
// Константы
|
|||
|
|
#определить ПИ 3.14159265358979323846
|
|||
|
|
#определить Е 2.71828182845904523536
|
|||
|
|
|
|||
|
|
#конецесли
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Пример программы с русской стандартной библиотекой
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
#включить "стандарт.з"
|
|||
|
|
|
|||
|
|
цел главн() {
|
|||
|
|
печать("Введите число: ");
|
|||
|
|
цел x;
|
|||
|
|
ввод("%d", &x);
|
|||
|
|
|
|||
|
|
цел квадрат = степень(x, 2);
|
|||
|
|
печать("Квадрат числа %d равен %d\n", x, квадрат);
|
|||
|
|
|
|||
|
|
печать("Синус числа: %f\n", синус(x));
|
|||
|
|
|
|||
|
|
символ *сообщение = выделить(100);
|
|||
|
|
если (сообщение != нуль) {
|
|||
|
|
копировать_строку(сообщение, "Привет, мир!");
|
|||
|
|
печать("%s\n", сообщение);
|
|||
|
|
освободить(сообщение);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
завершить(0);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Преимущества для образования
|
|||
|
|
|
|||
|
|
Русскоязычная стандартная библиотека станет мощным инструментом для обучения программированию, так как:
|
|||
|
|
|
|||
|
|
1. **Снижает порог входа**: студентам не нужно запоминать английские названия функций.
|
|||
|
|
2. **Ускоряет обучение**: можно сразу переходить к логике, а не тратить время на запоминание терминов.
|
|||
|
|
3. **Сохраняет совместимость**: при необходимости можно использовать английские имена.
|
|||
|
|
|
|||
|
|
### Статус
|
|||
|
|
|
|||
|
|
- ⏳ **Русификация стандартной библиотеки** — в планах.
|
|||
|
|
- ⏳ **Создание заголовочных файлов с русскими именами** — следующий этап.
|
|||
|
|
- ⏳ **Интеграция с компилятором** — после создания библиотеки.
|
|||
|
|
|
|||
|
|
## Настройка русской раскладки для Linux
|
|||
|
|
|
|||
|
|
В планах создание **настройки для русской раскладки клавиатуры в Linux**, чтобы программистам не приходилось переключаться между русской и английской раскладками при вводе знаков препинания.
|
|||
|
|
|
|||
|
|
### Проблема
|
|||
|
|
|
|||
|
|
При написании кода на русском языке программисты сталкиваются с необходимостью часто переключать раскладку:
|
|||
|
|
- Русская раскладка: буквы на русском, но знаки препинания (`.` , `,` , `;` , `:` , `[` , `]` , `{` , `}` , `(` , `)` , `!` , `?` , `@` , `#` , `$` , `%` , `^` , `&` , `*` , `-` , `_` , `+` , `=` , `~` , `|` , `\` , `/` , `<` , `>` ) находятся в других местах или недоступны.
|
|||
|
|
- Английская раскладка: знаки препинания на привычных местах, но буквы на английском.
|
|||
|
|
|
|||
|
|
Постоянное переключение раскладки замедляет написание кода и отвлекает от процесса.
|
|||
|
|
|
|||
|
|
### Решение
|
|||
|
|
|
|||
|
|
Создание **специальной настройки (раскладки или модификации)** для Linux, которая:
|
|||
|
|
|
|||
|
|
1. **Сохраняет расположение букв как в русской раскладке** (ЙЦУКЕН или ЙЦУКЕНГ).
|
|||
|
|
2. **Размещает знаки препинания на тех же клавишах, что и в английской раскладке** (`.` на той же клавише, где в английском, `,` на той же и т.д.).
|
|||
|
|
|
|||
|
|
В результате программист может:
|
|||
|
|
- Писать буквы на русском (без переключения).
|
|||
|
|
- Вводить знаки препинания на тех же клавишах, к которым привык в английской раскладке.
|
|||
|
|
|
|||
|
|
### Как это будет реализовано
|
|||
|
|
|
|||
|
|
1. **Создание файла настройки XKB (xkb)** — стандартный способ настройки раскладок в Linux (Xorg и Wayland).
|
|||
|
|
2. **Интеграция с системой** — установка через скрипт или пакет.
|
|||
|
|
|
|||
|
|
### Пример файла `ru_prog` (русская программистская раскладка)
|
|||
|
|
|
|||
|
|
```xkb
|
|||
|
|
// ru_prog - русская раскладка со знаками препинания как в английской
|
|||
|
|
xkb_symbols "prog" {
|
|||
|
|
include "ru(ru)"
|
|||
|
|
name[Group1] = "Russian (programming)";
|
|||
|
|
|
|||
|
|
// Переопределяем знаки препинания
|
|||
|
|
key <TLDE> { [ apostrophe, asciitilde ] }; // ` ~
|
|||
|
|
key <AE01> { [ 1, exclam ] }; // 1 !
|
|||
|
|
key <AE02> { [ 2, at ] }; // 2 @
|
|||
|
|
key <AE03> { [ 3, numbersign ] }; // 3 #
|
|||
|
|
key <AE04> { [ 4, dollar ] }; // 4 $
|
|||
|
|
key <AE05> { [ 5, percent ] }; // 5 %
|
|||
|
|
key <AE06> { [ 6, asciicircum ] }; // 6 ^
|
|||
|
|
key <AE07> { [ 7, ampersand ] }; // 7 &
|
|||
|
|
key <AE08> { [ 8, asterisk ] }; // 8 *
|
|||
|
|
key <AE09> { [ 9, parenleft ] }; // 9 (
|
|||
|
|
key <AE10> { [ 0, parenright ] }; // 0 )
|
|||
|
|
key <AE11> { [ minus, underscore ] }; // - _
|
|||
|
|
key <AE12> { [ equal, plus ] }; // = +
|
|||
|
|
|
|||
|
|
key <AD01> { [ q, Q ] }; // q
|
|||
|
|
key <AD02> { [ w, W ] }; // w
|
|||
|
|
key <AD03> { [ e, E ] }; // e
|
|||
|
|
key <AD04> { [ r, R ] }; // r
|
|||
|
|
key <AD05> { [ t, T ] }; // t
|
|||
|
|
key <AD06> { [ y, Y ] }; // y
|
|||
|
|
key <AD07> { [ u, U ] }; // u
|
|||
|
|
key <AD08> { [ i, I ] }; // i
|
|||
|
|
key <AD09> { [ o, O ] }; // o
|
|||
|
|
key <AD10> { [ p, P ] }; // p
|
|||
|
|
key <AD11> { [ bracketleft, braceleft ] }; // [ {
|
|||
|
|
key <AD12> { [ bracketright, braceright ] }; // ] }
|
|||
|
|
|
|||
|
|
key <AC01> { [ a, A ] }; // a
|
|||
|
|
key <AC02> { [ s, S ] }; // s
|
|||
|
|
key <AC03> { [ d, D ] }; // d
|
|||
|
|
key <AC04> { [ f, F ] }; // f
|
|||
|
|
key <AC05> { [ g, G ] }; // g
|
|||
|
|
key <AC06> { [ h, H ] }; // h
|
|||
|
|
key <AC07> { [ j, J ] }; // j
|
|||
|
|
key <AC08> { [ k, K ] }; // k
|
|||
|
|
key <AC09> { [ l, L ] }; // l
|
|||
|
|
key <AC10> { [ semicolon, colon ] }; // ; :
|
|||
|
|
key <AC11> { [ apostrophe, quotedbl ] }; // ' "
|
|||
|
|
|
|||
|
|
key <AB01> { [ z, Z ] }; // z
|
|||
|
|
key <AB02> { [ x, X ] }; // x
|
|||
|
|
key <AB03> { [ c, C ] }; // c
|
|||
|
|
key <AB04> { [ v, V ] }; // v
|
|||
|
|
key <AB05> { [ b, B ] }; // b
|
|||
|
|
key <AB06> { [ n, N ] }; // n
|
|||
|
|
key <AB07> { [ m, M ] }; // m
|
|||
|
|
key <AB08> { [ comma, less ] }; // , <
|
|||
|
|
key <AB09> { [ period, greater ] }; // . >
|
|||
|
|
key <AB10> { [ slash, question ] }; // / ?
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Альтернативный подход: использование `setxkbmap`
|
|||
|
|
|
|||
|
|
Для быстрой настройки можно использовать команду:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
setxkbmap -layout us,ru -variant ,prog -option grp:alt_shift_toggle
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Планируемые функции
|
|||
|
|
|
|||
|
|
1. **Установка через скрипт**: `./настроить_раскладку.sh` — автоматически добавляет раскладку в систему.
|
|||
|
|
2. **Переключение по горячим клавишам**: например, `Alt+Shift` переключает между стандартной русской и программистской русской раскладкой.
|
|||
|
|
3. **Интеграция с редакторами**: автоматическое переключение раскладки при открытии `.рс` файлов.
|
|||
|
|
4. **Документация**: инструкции для различных дистрибутивов Linux (Ubuntu, Fedora, Arch, etc.)
|
|||
|
|
|
|||
|
|
### Статус
|
|||
|
|
|
|||
|
|
- ⏳ **Создание файла XKB для русской программистской раскладки** — в планах.
|
|||
|
|
- ⏳ **Скрипт автоматической установки** — следующий этап.
|
|||
|
|
- ⏳ **Документация для различных дистрибутивов** — в планах.
|
|||
|
|
|
|||
|
|
## Сборка и тестирование
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Сборка компилятора
|
|||
|
|
make
|
|||
|
|
|
|||
|
|
# Запуск стандартных тестов
|
|||
|
|
make test
|
|||
|
|
|
|||
|
|
# Запуск русских тестов
|
|||
|
|
make test-ru
|
|||
|
|
|
|||
|
|
# Запуск всех тестов (стандартные + русские)
|
|||
|
|
make test-all
|
|||
|
|
|
|||
|
|
# Самосборка и тестирование stage2
|
|||
|
|
make test-stage2
|
|||
|
|
|
|||
|
|
# Очистка собранных файлов
|
|||
|
|
make clean
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Благодарности
|
|||
|
|
|
|||
|
|
Особая благодарность:
|
|||
|
|
- **Rui Ueyama** за создание [chibicc](https://github.com/rui314/chibicc) — образцово-простого и образовательного компилятора.
|
|||
|
|
- **Alexandre Gaigalas** за [c89cc.sh](https://gist.github.com/alganet/2b89c4368f8d23d033961d8a3deb5c19) — демонстрацию минимализма в реализации компилятора.
|
|||
|
|
|
|||
|
|
## Статус
|
|||
|
|
|
|||
|
|
- ✅ Все основные конструкции переведены и протестированы.
|
|||
|
|
- ✅ Двуязычный синтаксис полностью работоспособен.
|
|||
|
|
- ✅ Поддержка русского синтаксиса и смешанного стиля успешно проходит 70+ тестов.
|
|||
|
|
- ✅ Русские имена файлов и расширений поддерживаются.
|
|||
|
|
- ✅ Самосборка (self-hosting) успешно работает.
|
|||
|
|
- ✅ Функция `main` переименована в `главн`.
|
|||
|
|
- ⏳ Миграция исходного кода на русский синтаксис — в процессе.
|
|||
|
|
- ⏳ Портирование КВС с Python на C — в планах.
|
|||
|
|
- ⏳ Расширение для подсветки синтаксиса VS Code / VS Codium — в планах.
|
|||
|
|
- ⏳ Русификация стандартной библиотеки — в планах.
|
|||
|
|
- ⏳ Настройка русской раскладки для Linux — в планах.
|
|||
|
|
|
|||
|
|
```
|