[English](README.md) • [Русский](README_RU.md) • [简体中文](README_ZH_CN.md) • [繁體中文](README_ZH_TW.md) • [Español](README_ES.md) • [Italiano](README_IT.md)
# Zen C
**Современная эргономика. Никаких накладных расходов. Чистый Си.**
[]()
[]()
[]()
[]()
*Пишите как на высокоуровневом языке, запускайте как Си.*
---
## Обзор
**Zen C** — это современный язык системного программирования, который компилируется в человекочитаемом `GNU C`/`C11`. Он предоставляет богатый набор возможностей, включая вывод типов, сопоставление с паттернами, генерику, трейты, async/await и ручное управление памятью с возможностями RAII, при этом поддерживая 100% совместимость с ABI Си.
## Сообщество
Приглашаем вас присоединиться к нам на официальном Discord-сервере Zen C! Здесь можно обсуждать проект, делиться примерами, задавать вопросы и сообщать об ошибках.
- Discord: [Присоединиться](https://discord.com/invite/q6wEsCmkJP)
---
## Содержание
- [Обзор](#обзор)
- [Сообщество](#сообщество)
- [Быстрый старт](#быстрый-старт)
- [Установка](#установка)
- [Использование](#использование)
- [Переменные окружения](#переменные-окружения)
- [Справочник](#справочник)
- [1. Переменные и константы](#1-переменные-и-константы)
- [2. Примитивные типы](#2-примитивные-типы)
- [3. Составные типы](#3-составные-типы)
- [Массивы](#массивы)
- [Кортежи](#кортежи)
- [Структуры](#структуры)
- [Непрозрачные структуры](#непрозрачные-структуры)
- [Перечисления](#перечисления)
- [Объединения](#объединения)
- [Псевдонимы типов](#псевдонимы-типов)
- [Непрозрачные псевдонимы типов](#непрозрачные-псевдонимы-типов)
- [4. Функции и лямбды](#4-функции-и-лямбды)
- [Функции](#функции)
- [Константные аргументы](#константные-аргументы)
- [Аргументы по умолчанию](#аргументы-по-умолчанию)
- [Лямбды](#лямбды)
- [Сырые указатели на функции](#сырые-указатели-на-функции)
- [Вариадические функции](#вариадические-функции)
- [5. Управление потоком](#5-управление-потоком)
- [Условные операторы](#условные-операторы)
- [Сопоставление с образцом](#сопоставление-с-образцом)
- [Циклы](#циклы)
- [Продвинутое управление](#продвинутое-управление)
- [6. Операторы](#6-операторы)
- [Перегружаемые операторы](#перегружаемые-операторы)
- [Синтаксический сахар](#синтаксический-сахар)
- [7. Печать и интерполяция строк](#7-печать-и-интерполяция-строк)
- [Ключевые слова](#ключевые-слова)
- [Сокращения](#сокращения)
- [Интерполяция строк (F-строки)](#интерполяция-строк-f-строки)
- [Запросы ввода (`?`)](#запросы-ввода-)
- [8. Управление памятью](#8-управление-памятью)
- [Autofree](#autofree)
- [Семантика ресурсов (Move по умолчанию)](#семантика-ресурсов-move-по-умолчанию)
- [RAII / Трейт Drop](#raii--трейт-drop)
- [9. Объектно-ориентированное программирование](#9-объектно-ориентированное-программирование)
- [Методы](#методы)
- [Трейты](#трейты)
- [Стандартные трейты](#стандартные-трейты)
- [Композиция](#композиция)
- [10. Обобщения](#10-обобщения)
- [11. Параллелизм (Async/Await)](#11-параллелизм-asyncawait)
- [12. Метапрограммирование](#12-метапрограммирование)
- [Embed](#embed)
- [Плагины](#плагины)
- [Обобщённые макросы C](#обобщённые-макросы-c)
- [13. Атрибуты](#13-атрибуты)
- [Пользовательские атрибуты](#пользовательские-атрибуты)
- [Умные производные](#умные-производные)
- [14. Встроение ассемблера](#14-встроение-ассемблера)
- [Базовое использование](#базовое-использование)
- [Именованные ограничения](#именованные-ограничения)
- [15. Директивы сборки](#15-директивы-сборки)
- [16. Ключевые слова](#16-ключевые-слова)
- [17. Взаимодействие с Си](#17-взаимодействие-с-Си)
- [Стандартная библиотека](#стандартная-библиотека)
- [Инструменты](#инструменты)
- [Языковой сервер (LSP)](#языковой-сервер-lsp)
- [Поддержка компилятора и совместимость](#поддержка-компилятора-и-совместимость)
- [Статус набора тестов](#статус-набора-тестов)
- [Сборка с Zig](#сборка-с-zig)
- [Взаимодействие с C++](#взаимодействие-с-c)
- [Взаимодействие с CUDA](#взаимодействие-с-cuda)
- [Взаимодействие с Objective-C](#взаимодействие-с-objective-c)
- [Поддержка C23](#поддержка-c23)
- [Участие в разработке](#участие-в-разработке)
- [Благодарности](#благодарности)
---
## Быстрый старт
### Установка
```bash
git clone https://github.com/z-libs/Zen-C.git
cd Zen-C
make
sudo make install
```
### Портативная сборка (APE)
Zen C можно скомпилировать как **Actually Portable Executable (APE)** с помощью [Cosmopolitan Libc](https://github.com/jart/cosmopolitan). Это создаёт один исполняемый файл (`.com`), работающий нативно на Linux, macOS, Windows, FreeBSD, OpenBSD и NetBSD на архитектурах x86_64 и aarch64.
**Требования:**
- Набор инструментов `cosmocc` (должен быть в PATH)
**Сборка и установка:**
```bash
make ape
sudo env "PATH=$PATH" make install-ape
```
**Созданные файлы:**
- `out/bin/zc.com`: Портативный компилятор Zen-C с встроенной стандартной библиотекой.
- `out/bin/zc-boot.com`: Установщик для создания новых проектов Zen-C.
**Использование:**
```bash
# Запустить на любой поддерживаемой ОС
./out/bin/zc.com build hello.zc -o hello
```
### Использование
```bash
# Компилировать и запустить
zc run hello.zc
# Создать исполняемый файл
zc build hello.zc -o hello
# Интерактивная оболочка
zc repl
```
### Переменные окружения
Установите `ZC_ROOT` для указания пути к стандартной библиотеке (для импортов типа `import "std/vec.zc"`). Это позволяет запускать `zc` из любого каталога.
```bash
export ZC_ROOT=/path/to/Zen-C
```
---
## Справочник
### 1. Переменные и константы
Zen C различает константы времени компиляции и переменные времени выполнения.
#### Манифест-константы (`def`)
Значения, которые существуют только во время компиляции (встраиваются в код). Используйте их для размеров массивов, фиксированной конфигурации и магических чисел.
```zc
def MAX_SIZE = 1024;
let buffer: char[MAX_SIZE]; // Допустимый размер массива
```
#### Переменные (`let`)
Расположения в памяти. Могут быть изменяемыми или только для чтения (`const`).
```zc
let x = 10; // Переменная
x = 20; // ОК
let y: const int = 10; // Только для чтения (квалификатор типа)
// y = 20; // Ошибка: невозможно присвоить const переменной
```
> **Вывод типов**: Zen C автоматически выводит типы для инициализированных переменных. Он компилируется в C23 `auto` на поддерживаемых компиляторах или, в противном случае, с помощью GCC `__auto_type`.
### 2. Примитивные типы
| Тип | Эквивалент Си | Описание |
|:----------------------------------|:---------------------------|:------------------------------------------------|
| `int`, `uint` | `int32_t`, `uint32_t` | 32-битовое целое число со знаком/без знака |
| `c_char`, `c_uchar` | `char`, `unsigned char` | C char / unsigned char (Interop) |
| `c_short`, `c_ushort` | `short`, `unsigned short` | C short / unsigned short (Interop) |
| `c_int`, `c_uint` | `int`, `unsigned int` | C int / unsigned int (Interop) |
| `c_long`, `c_ulong` | `long`, `unsigned long` | C long / unsigned long (Interop) |
| `I8` .. `I128` или `i8` .. `i128` | `int8_t` .. `__int128_t` | Целые числа со знаком фиксированной ширины |
| `U8` .. `U128` или `u8` .. `u128` | `uint8_t` .. `__uint128_t` | Целые числа без знака фиксированной ширины |
| `isize`, `usize` | `ptrdiff_t`, `size_t` | Целые числа размером с указатель |
| `byte` | `uint8_t` | Псевдоним для U8 |
| `F32`, `F64` или `f32`, `f64` | `float`, `double` | Числа с плавающей точкой |
| `bool` | `bool` | `true` или `false` |
| `char` | `char` | Одиночный символ |
| `string` | `char*` | Си-строка (с нулевым завершением) |
| `U0`, `u0`, `void` | `void` | Пустой тип |
| `iN` (например, `i256`) | `_BitInt(N)` | Целое число со знаком произвольной ширины (C23) |
| `uN` (например, `u42`) | `unsigned _BitInt(N)` | Целое число без знака произвольной ширины (C23) |
> **Лучшие практики для портативного кода**
>
> - Используйте **Портативные типы** (`int`, `uint`, `i64`, `u8` и т.д.) для чистой логики Zen C. `int` гарантированно имеет "ширину" в 32 бита и является знаковым на всех архитектурах.
> - Используйте **Типы Interop C** (`c_int`, `c_char`, `c_long`) **только** при взаимодействии с библиотеками C (FFI). Их размер зависит от платформы и компилятора C (например, размер `c_long` отличается между Windows и Linux).
> - Используйте `isize` и `usize` для индексирования массивов и арифметики указателей на память.
### 3. Составные типы
#### Массивы
Массивы фиксированного размера с семантикой значения.
```zc
def SIZE = 5;
let ints: int[SIZE] = [1, 2, 3, 4, 5];
let zeros: [int; SIZE]; // Инициализировано нулями
```
#### Кортежи
Группируйте несколько значений вместе, получайте доступ к элементам по индексу.
```zc
let pair = (1, "Hello");
let x = pair.0; // 1
let s = pair.1; // "Hello"
```
**Множественные возвращаемые значения**
Функции могут возвращать кортежи для предоставления нескольких результатов:
```zc
fn add_and_subtract(a: int, b: int) -> (int, int) {
return (a + b, a - b);
}
let result = add_and_subtract(3, 2);
let sum = result.0; // 5
let diff = result.1; // 1
```
**Деструктуризация**
Кортежи могут быть деструктурированы прямо в переменные:
```zc
let (sum, diff) = add_and_subtract(3, 2);
// sum = 5, diff = 1
```
#### Структуры
Структуры данных с опциональными битовыми полями.
```zc
struct Point {
x: int;
y: int;
}
// Инициализация структуры
let p = Point { x: 10, y: 20 };
// Битфилды
struct Flags {
valid: U8 : 1;
mode: U8 : 3;
}
```
> **Примечание**: Структуры используют [Move Semantics](#семантика-ресурсов-move-по-умолчанию) по умолчанию. Доступ к полям можно получить через `.` даже на указателях (Auto-Dereference).
#### Непрозрачные структуры
Вы можете определить структуру как `opaque`, чтобы ограничить доступ к её полям только определяющим модулем, при этом позволяя структуре размещаться на стеке (размер известен).
```zc
// В user.zc
opaque struct User {
id: int;
name: string;
}
fn new_user(name: string) -> User {
return User{id: 1, name: name}; // ОК: внутри модуля
}
// В main.zc
import "user.zc";
fn main() {
let u = new_user("Alice");
// let id = u.id; // Ошибка: нет доступа к приватному полю 'id'
}
```
#### Перечисления
Теговые объединения (Sum types), способные содержать данные.
```zc
enum Shape {
Circle(float), // Держит радиус
Rect(float, float), // Держит ширину, высоту
Point // Нет данных
}
```
#### Объединения
Стандартные C объединения (небезопасно).
```zc
union Data {
i: int;
f: float;
}
```
#### Псевдонимы типов
Создайте новое имя для существующего типа.
```zc
alias ID = int;
alias PointMap = Map;
```
#### Непрозрачные псевдонимы типов
Вы можете определить псевдоним типа как `opaque`, чтобы создать новый тип, который отличается от своего базового типа вне определяющего модуля. Это обеспечивает сильную инкапсуляцию и безопасность типов без накладных расходов времени выполнения структуры-оболочки.
```zc
// В library.zc
opaque alias Handle = int;
fn make_handle(v: int) -> Handle {
return v; // Неявное преобразование разрешено внутри модуля
}
// В main.zc
import "library.zc";
fn main() {
let h: Handle = make_handle(42);
// let i: int = h; // Ошибка: проверка типа не прошла
// let h2: Handle = 10; // Ошибка: проверка типа не прошла
}
```
### 4. Функции и лямбды
#### Функции
```zc
fn add(a: int, b: int) -> int {
return a + b;
}
// Именованные аргументы поддерживаются при вызовах
add(a: 10, b: 20);
```
> **Примечание**: Именованные аргументы должны строго следовать порядку определённых параметров. `add(b: 20, a: 10)` недопустимо.
#### Константные аргументы
Аргументы функции могут быть помечены как `const` для обеспечения семантики только для чтения. Это квалификатор типа, а не манифест-константа.
```zc
fn print_val(v: const int) {
// v = 10; // Ошибка: невозможно присвоить const переменной
println "{v}";
}
```
#### Аргументы по умолчанию
Функции могут определять значения по умолчанию для завершающих аргументов. Это могут быть литералы, выражения или допустимый код Zen C (например, конструкторы структур).
```zc
// Простое значение по умолчанию
fn increment(val: int, amount: int = 1) -> int {
return val + amount;
}
// Значение по умолчанию как выражение (вычисляется в месте вызова)
fn offset(val: int, pad: int = 10 * 2) -> int {
return val + pad;
}
// Значение по умолчанию для структуры
struct Config { debug: bool; }
fn init(cfg: Config = Config { debug: true }) {
if cfg.debug { println "Debug Mode"; }
}
fn main() {
increment(10); // 11
offset(5); // 25
init(); // Выводит "Debug Mode"
}
```
#### Лямбды
Анонимные функции, которые могут захватывать своё окружение.
```zc
let factor = 2;
let double = x -> x * factor; // Синтаксис стрелок
let full = fn(x: int) -> int { return x * factor; }; // Блочный синтаксис
```
#### Сырые указатели на функции
Zen C поддерживает сырые (Raw) указатели на функции Си, используя синтаксис `fn*`. Это позволяет беспрепятственно взаимодействовать с библиотеками Си, которые ожидают указателей на функции без накладных расходов замыкания.
```zc
// Функция, принимающая сырой указатель на функцию
fn set_callback(cb: fn*(int)) {
cb(42);
}
// Функция, возвращающая сырой указатель на функцию
fn get_callback() -> fn*(int) {
return my_handler;
}
// Поддерживаются указатели на указатели функций (fn**)
let pptr: fn**(int) = &ptr;
```
#### Вариадические функции
Функции могут принимать переменное число аргументов, используя `...` и тип `va_list`.
```zc
fn log(lvl: int, fmt: char*, ...) {
let ap: va_list;
va_start(ap, fmt);
vprintf(fmt, ap); // Используем C stdio
va_end(ap);
}
```
### 5. Управление потоком
#### Условные операторы
```zc
if x > 10 {
print("Large");
} else if x > 5 {
print("Medium");
} else {
print("Small");
}
// Тернарно
let y = x > 10 ? 1 : 0;
```
#### Сопоставление с образцом
Мощная альтернатива `switch`.
```zc
match val {
1 => { print "One" },
2 || 3 => { print "Two or Three" }, // ИЛИ с ||
4 or 5 => { print "Four or Five" }, // ИЛИ с 'or'
6, 7, 8 => { print "Six to Eight" }, // ИЛИ с запятой
10 .. 15 => { print "10 to 14" }, // Исключающий диапазон (устаревший)
10 ..< 15 => { print "10 to 14" }, // Исключающий диапазон (явно)
20 ..= 25 => { print "20 to 25" }, // Включающий диапазон
_ => { print "Other" },
}
// Деструктуризация перечислений
match shape {
Shape::Circle(r) => { println "Radius: {r}" },
Shape::Rect(w, h) => { println "Area: {w*h}" },
Shape::Point => { println "Point" },
}
```
#### Привязка ссылок
Чтобы проверить значение без передачи владения (перемещения), используйте ключевое слово `ref` в паттерне. Это необходимо для типов, которые реализуют Move Semantics (такие как `Option`, `Result`, структуры без Copy).
```zc
let opt = Some(NonCopyVal{...});
match opt {
Some(ref x) => {
// 'x' - это указатель на значение внутри 'opt'
// 'opt' НЕ перемещается/не потребляется здесь
println "{x.field}";
},
None => {}
}
```
#### Циклы
```zc
// Диапазон
for i in 0..10 { ... } // Исключительно (0 до 9)
for i in 0..<10 { ... } // Исключительно (явно)
for i in 0..=10 { ... } // Включительно (0 до 10)
for i in 0..10 step 2 { ... }
// Итератор (Vec или пользовательский Iterable)
for item in vec { ... }
// Итерация по массивам фиксированного размера напрямую
let arr: int[5] = [1, 2, 3, 4, 5];
for val in arr {
// val - это int
println "{val}";
}
// While
while x < 10 { ... }
// Бесконечный цикл с меткой
outer: loop {
if done { break outer; }
}
// Повторить N раз
for _ in 0..5 { ... }
```
#### Продвинутое управление
```zc
// Guard: выполнить else и вернуться, если условие ложно
guard ptr != NULL else { return; }
// Unless: если не верно
unless is_valid { return; }
```
### 6. Операторы
Zen C поддерживает перегрузку операторов для пользовательских структур путём реализации специфических имён методов.
#### Перегружаемые операторы
| Категория | Оператор | Имя метода |
|:---------------|:------------------------|:----------------------------------|
| **Арифметика** | `+`, `-`, `*`, `/`, `%` | `add`, `sub`, `mul`, `div`, `rem` |
| **Сравнение** | `==`, `!=` | `eq`, `neq` |
| | `<`, `>`, `<=`, `>=` | `lt`, `gt`, `le`, `ge` |
| **Побитовые** | `&`, `\|`, `^` | `bitand`, `bitor`, `bitxor` |
| | `<<`, `>>` | `shl`, `shr` |
| **Унарные** | `-` | `neg` |
| | `!` | `not` |
| | `~` | `bitnot` |
| **Индекс** | `a[i]` | `get(a, i)` |
| | `a[i] = v` | `set(a, i, v)` |
> **Примечание о равенстве строк**:
> - `string == string` выполняет **сравнение значений** (эквивалент `strcmp`).
> - `char* == char*` выполняет **сравнение указателей** (проверяет адреса памяти).
> - Смешанные сравнения (например `string == char*`) по умолчанию используют **сравнение указателей**.
**Пример:**
```zc
impl Point {
fn add(self, other: Point) -> Point {
return Point{x: self.x + other.x, y: self.y + other.y};
}
}
let p3 = p1 + p2; // Вызывает p1.add(p2)
```
| `\|>` | Pipeline | `x \|> f(y)` раскрывается в `f(x, y)` |
| `??` | Null Coalescing | `val ?? default` возвращает `default`, если `val` равно NULL (указатели) |
| `??=` | Null Assignment | `val ??= init` присваивает, если `val` равно NULL |
| `?.` | Safe Navigation | `ptr?.field` получает доступ к полю только если `ptr` не равно NULL |
| `?` | Try Operator | `res?` возвращает ошибку, если она присутствует (типы Result/Option) |
**Auto-Dereference**:
Доступ к полям указателя (`ptr.field`) и вызовы методов (`ptr.method()`) автоматически разыменовывают указатель, эквивалентно `(*ptr).field`.
### 7. Печать и интерполяция строк
Zen C предоставляет универсальные опции для печати на консоль, включая ключевые слова и краткие сокращения.
#### Ключевые слова
- `print "text"`: Выводит на `stdout` без перевода строки.
- `println "text"`: Выводит на `stdout` с переводом строки.
- `eprint "text"`: Выводит на `stderr` без перевода строки.
- `eprintln "text"`: Выводит на `stderr` с переводом строки.
#### Сокращения
Zen C позволяет использовать строковые литералы непосредственно как операторы для быстрой печати:
- `"Hello World"`: Эквивалент `println "Hello World"`. (Неявно добавляет перевод строки)
- `"Hello World"..`: Эквивалент `print "Hello World"`. (Без перевода строки)
- `!"Error"`: Эквивалент `eprintln "Error"`. (Вывод на stderr)
- `!"Error"..`: Эквивалент `eprint "Error"`. (Вывод на stderr, без перевода строки)
#### Интерполяция строк (F-строки)
Вы можете встраивать выражения непосредственно в строковые литералы, используя синтаксис `{}`. Это работает со всеми методами печати и сокращениями строк.
```zc
let x = 42;
let name = "Zen";
println "Value: {x}, Name: {name}";
"Value: {x}, Name: {name}"; // Сокращение для println
```
#### Запросы ввода (`?`)
Zen C поддерживает сокращение для запроса ввода пользователя с использованием префикса `?`.
- `? "Prompt text"`: Выводит подсказку (без перевода строки) и ожидает ввода (читает строку).
- `? "Enter age: " (age)`: Выводит подсказку и сканирует ввод в переменную `age`.
- Спецификаторы формата автоматически выводятся на основе типа переменной.
```zc
let age: int;
? "How old are you? " (age);
println "You are {age} years old.";
```
### 8. Управление памятью
Zen C позволяет ручное управление памятью с удобными помощниками.
#### Defer
Выполните код при выходе из текущей области видимости. Операторы Defer выполняются в порядке LIFO (последний вошёл, первый вышел).
```zc
let f = fopen("file.txt", "r");
defer fclose(f);
```
> Чтобы предотвратить неопределённое поведение, операторы управления потоком (`return`, `break`, `continue`, `goto`) **недопустимы** внутри блока `defer`.
#### Autofree
Автоматически освобождает переменную при выходе из области видимости.
```zc
autofree let types = malloc(1024);
```
#### Семантика ресурсов (Move по умолчанию)
Zen C рассматривает типы с деструкторами (такие как `File`, `Vec` или выделённые malloc указатели) как **Ресурсы**. Чтобы предотвратить ошибки двойного освобождения, ресурсы не могут быть неявно дублированы.
- **Move по умолчанию**: Присвоение переменной ресурса передаёт владение. Исходная переменная становится недействительной (Moved).
- **Типы Copy**: Типы без деструкторов могут выбрать поведение `Copy`, делая присвоение дублированием.
**Диагностика и философия**:
Если вы видите ошибку "Use of moved value", компилятор говорит вам: *"Этот тип владеет ресурсом (типа память или дескриптор) и слепое копирование небезопасно."*
> **Контраст:** В отличие от C/C++, Zen C не неявно дублирует значения, владеющие ресурсами.
**Аргументы функции**:
Передача значения функции следует тем же правилам, что и присвоение: ресурсы перемещаются, если только они не передаются по ссылке.
```zc
fn process(r: Resource) { ... } // 'r' перемещается в функцию
fn peek(r: Resource*) { ... } // 'r' заимствуется (ссылка)
```
**Явное клонирование**:
Если вы *действительно* хотите две копии ресурса, сделайте это явным:
```zc
let b = a.clone(); // Вызывает метод 'clone' из трейта Clone
```
**Opt-in Copy (типы значений)**:
Для малых типов без деструкторов:
```zc
struct Point { x: int; y: int; }
impl Copy for Point {} // Opt-in для неявного дублирования
fn main() {
let p1 = Point { x: 1, y: 2 };
let p2 = p1; // Скопирована. p1 остаётся допустимой.
}
```
#### RAII / Трейт Drop
Реализуйте `Drop` для автоматического запуска логики очистки.
```zc
impl Drop for MyStruct {
fn drop(self) {
self.free();
}
}
```
### 9. Объектно-ориентированное программирование
#### Методы
Определяйте методы на типах с помощью `impl`.
```zc
impl Point {
// Статический метод (соглашение конструктора)
fn new(x: int, y: int) -> Self {
return Point{x: x, y: y};
}
// Метод экземпляра
fn dist(self) -> float {
return sqrt(self.x * self.x + self.y * self.y);
}
}
```
#### Трейты
Определяйте общее поведение.
```zc
struct Circle { radius: f32; }
trait Drawable {
fn draw(self);
}
impl Drawable for Circle {
fn draw(self) { ... }
}
let circle = Circle{};
let drawable: Drawable = &circle;
```
#### Стандартные трейты
Zen C включает стандартные трейты, которые интегрируются с синтаксисом языка.
**Iterable**
Реализуйте `Iterable` для включения циклов `for-in` для ваших пользовательских типов.
```zc
import "std/iter.zc"
// Определите итератор
struct MyIter {
curr: int;
stop: int;
}
impl MyIter {
fn next(self) -> Option {
if self.curr < self.stop {
self.curr += 1;
return Option::Some(self.curr - 1);
}
return Option::None();
}
}
// Реализуйте Iterable
impl MyRange {
fn iterator(self) -> MyIter {
return MyIter{curr: self.start, stop: self.end};
}
}
// Используйте в цикле
for i in my_range {
println "{i}";
}
```
**Drop**
Реализуйте `Drop` для определения деструктора, который запускается при выходе объекта из области видимости (RAII).
```zc
import "std/mem.zc"
struct Resource {
ptr: void*;
}
impl Drop for Resource {
fn drop(self) {
if self.ptr != NULL {
free(self.ptr);
}
}
}
```
> **Примечание**: Если переменная перемещена, `drop` не вызывается для оригинала. Подробнее в [семантике ресурсов](#семантика-ресурсов-move-по-умолчанию).
**Copy**
Маркерный трейт для выбора поведения `Copy` (неявное дублирование) вместо Move семантики. Используется через `@derive(Copy)`.
> **Правило:** Типы, которые реализуют `Copy`, не должны определять деструктор (`Drop`).
```zc
@derive(Copy)
struct Point { x: int; y: int; }
fn main() {
let p1 = Point{x: 1, y: 2};
let p2 = p1; // Скопирована! p1 остаётся допустимой.
}
```
**Clone**
Реализуйте `Clone` для разрешения явного дублирования типов, владеющих ресурсами.
```zc
import "std/mem.zc"
struct MyBox { val: int; }
impl Clone for MyBox {
fn clone(self) -> MyBox {
return MyBox{val: self.val};
}
}
fn main() {
let b1 = MyBox{val: 42};
let b2 = b1.clone(); // Явное копирование
}
```
#### Композиция
Используйте `use` для встраивания других структур. Вы можете либо смешивать их (уплощение полей), либо давать им названия (вложение полей).
```zc
struct Entity { id: int; }
struct Player {
// Миксин (без имени): уплощает поля
use Entity; // добавляет 'id' в Player напрямую
name: string;
}
struct Match {
// Композиция (с именем): вложение полей
use p1: Player; // доступ через match.p1
use p2: Player; // доступ через match.p2
}
```
### 10. Обобщения
Типобезопасные шаблоны для структур и функций.
```zc
// Обобщённая структура
struct Box {
item: T;
}
// Обобщённая функция
fn identity(val: T) -> T {
return val;
}
// Обобщения с несколькими параметрами
struct Pair {
key: K;
value: V;
}
```
### 11. Параллелизм (Async/Await)
Встроен на основе pthreads.
```zc
async fn fetch_data() -> string {
// Запускается в фоне
return "Data";
}
fn main() {
let future = fetch_data();
let result = await future;
}
```
### 12. Метапрограммирование
#### Comptime
Запускайте код при компиляции для генерации исходного кода или печати сообщений.
```zc
comptime {
// Генерируйте код при компиляции (выводится на stdout)
println "let build_date = \"2024-01-01\";";
}
println "Build Date: {build_date}";
```
#### Embed
Встраивайте файлы как указанные типы.
```zc
// По умолчанию (Slice_char)
let data = embed "assets/logo.png";
// Типизированное встраивание
let text = embed "shader.glsl" as string; // Встроить как C-строку
let rom = embed "bios.bin" as u8[1024]; // Встроить как фиксированный массив
let wav = embed "sound.wav" as u8[]; // Встроить как Slice_u8
```
#### Плагины
Импортируйте плагины компилятора для расширения синтаксиса.
```zc
import plugin "regex"
let re = regex! { ^[a-z]+$ };
```
#### Обобщённые макросы C
Передавайте макросы препроцессора в C.
> **Совет**: Для простых констант используйте `def`. Используйте `#define`, когда вам нужны макросы препроцессора C или флаги условной компиляции.
```zc
#define MAX_BUFFER 1024
```
### 13. Атрибуты
Украшайте функции и структуры для изменения поведения компилятора.
| Атрибут | Область | Описание |
|:---------------------|:----------|:----------------------------------------------------------------------------------------------|
| `@must_use` | Fn | Предупредить, если возвращаемое значение проигнорировано. |
| `@deprecated("msg")` | Fn/Struct | Предупредить при использовании с сообщением. |
| `@inline` | Fn | Подсказка компилятору встроить. |
| `@noinline` | Fn | Предотвратить встраивание. |
| `@packed` | Struct | Удалить заполнение между полями. |
| `@align(N)` | Struct | Принудительное выравнивание на N байт. |
| `@constructor` | Fn | Запустить перед main. |
| `@destructor` | Fn | Запустить после выхода из main. |
| `@unused` | Fn/Var | Подавить предупреждения о неиспользуемых переменных. |
| `@weak` | Fn | Слабая символьная компоновка. |
| `@section("name")` | Fn | Поместить код в специальный раздел. |
| `@noreturn` | Fn | Функция не возвращается (например exit). |
| `@pure` | Fn | Функция не имеет побочных эффектов (подсказка оптимизации). |
| `@cold` | Fn | Функция вряд ли будет выполняться (подсказка предсказания ветви). |
| `@hot` | Fn | Функция часто выполняется (подсказка оптимизации). |
| `@export` | Fn/Struct | Экспортировать символ (видимость по умолчанию). |
| `@global` | Fn | CUDA: Точка входа ядра (`__global__`). |
| `@device` | Fn | CUDA: Функция устройства (`__device__`). |
| `@host` | Fn | CUDA: Функция хоста (`__host__`). |
| `@comptime` | Fn | Вспомогательная функция, доступная для выполнения во время компиляции. |
| `@derive(...)` | Struct | Автоматически реализовать трейты. Поддерживает `Debug`, `Eq` (Smart Derive), `Copy`, `Clone`. |
| `@ctype("type")` | Fn Param | Переопределяет созданный тип C для параметра. |
| `@` | Any | Передаёт пользовательские атрибуты в C (например `@flatten`, `@alias("name")`). |
#### Пользовательские атрибуты
Zen C поддерживает мощную систему **Пользовательских атрибутов**, которая позволяет использовать любой `__attribute__` GCC/Clang прямо в вашем коде. Любой атрибут, который не явно признан компилятором Zen C, рассматривается как обобщённый атрибут и передаётся в сгенерированный код C.
Это обеспечивает доступ к продвинутым функциям компилятора, оптимизациям и директивам компоновщика без необходимости явной поддержки в ядре языка.
#### Отображение синтаксиса
Атрибуты Zen C отображаются прямо на атрибуты Си:
- `@name` → `__attribute__((name))`
- `@name(args)` → `__attribute__((name(args)))`
- `@name("string")` → `__attribute__((name("string")))`
#### Умные производные
Zen C предоставляет "Умные производные", которые уважают Move Semantics:
- **`@derive(Eq)`**: Генерирует метод равенства, который принимает аргументы по ссылке (`fn eq(self, other: T*)`).
- При сравнении двух структур без Copy (`a == b`), компилятор автоматически передаёт `b` по ссылке (`&b`), чтобы избежать его перемещения.
- Рекурсивные проверки равенства на полях также предпочитают доступ по указателю, чтобы предотвратить передачу владения.
### 14. Встроение ассемблера
Zen C предоставляет первоклассную поддержку встроения ассемблера прямо в код, транспилируя в GCC-стиле расширенный `asm`.
#### Базовое использование
Напишите сырой ассемблер в блоках `asm`. Строки автоматически конкатенируются.
```zc
asm {
"nop"
"mfence"
}
```
#### Volatile
Предотвратите оптимизацию ассемблера компилятором, который имеет побочные эффекты.
```zc
asm volatile {
"rdtsc"
}
```
#### Именованные ограничения
Zen C упрощает сложный синтаксис ограничений GCC с именованными привязками.
```zc
// Синтаксис: : out(variable) : in(variable) : clobber(reg)
// Использует синтаксис заполнителя {variable} для читаемости
fn add_five(x: int) -> int {
let result: int;
asm {
"mov {x}, {result}"
"add $5, {result}"
: out(result)
: in(x)
: clobber("cc")
}
return result;
}
```
| Тип | Синтаксис | Эквивалент GCC |
|:------------|:----------------------|:-----------------|
| **Output** | `: out(variable)` | `"=r"(variable)` |
| **Input** | `: in(variable)` | `"r"(variable)` |
| **Clobber** | `: clobber("rax")` | `"rax"` |
| **Memory** | `: clobber("memory")` | `"memory"` |
> **Примечание:** При использовании синтаксиса Intel (через `-masm=intel`) убедитесь, что ваша сборка правильно настроена (например, `//> cflags: -masm=intel`). TCC не поддерживает синтаксис Intel ассемблера.
### 15. Директивы сборки
Zen C поддерживает специальные комментарии в начале вашего исходного файла для настройки процесса сборки без необходимости сложной системы сборки или Makefile.
| Директива | Аргументы | Описание |
|:------------------|:----------------------------|:---------------------------------------------------------|
| `//> link:` | `-lfoo` или `path/to/lib.a` | Ссылка на библиотеку или объектный файл. |
| `//> lib:` | `path/to/libs` | Добавить путь поиска библиотеки (`-L`). |
| `//> include:` | `path/to/headers` | Добавить путь поиска заголовков (`-I`). |
| `//> framework:` | `Cocoa` | Ссылка на фреймворк macOS. |
| `//> cflags:` | `-Wall -O3` | Передать произвольные флаги компилятору C. |
| `//> define:` | `MACRO` или `KEY=VAL` | Определить макрос препроцессора (`-D`). |
| `//> pkg-config:` | `gtk+-3.0` | Запустить `pkg-config` и добавить `--cflags` и `--libs`. |
| `//> shell:` | `command` | Выполнить команду оболочки во время сборки. |
| `//> get:` | `http://url/file` | Загрузить файл, если конкретный файл не существует. |
#### Возможности
**1. Защита ОС**
Префиксируйте директивы названием ОС, чтобы применить их только на определённых платформах.
Поддерживаемые префиксы: `linux:`, `windows:`, `macos:` (или `darwin:`).
```zc
//> linux: link: -lm
//> windows: link: -lws2_32
//> macos: framework: Cocoa
```
**2. Расширение переменных окружения**
Используйте синтаксис `${VAR}` для расширения переменных окружения в ваших директивах.
```zc
//> include: ${HOME}/mylib/include
//> lib: ${ZC_ROOT}/std
```
#### Примеры
```zc
//> include: ./include
//> lib: ./libs
//> link: -lraylib -lm
//> cflags: -Ofast
//> pkg-config: gtk+-3.0
import "raylib.h"
fn main() { ... }
```
### 16. Ключевые слова
Следующие ключевые слова зарезервированы в Zen C.
#### Объявления
`alias`, `def`, `enum`, `fn`, `impl`, `import`, `let`, `module`, `opaque`, `struct`, `trait`, `union`, `use`
#### Управление потоком
`async`, `await`, `break`, `catch`, `continue`, `defer`, `else`, `for`, `goto`, `guard`, `if`, `loop`, `match`, `return`, `try`, `unless`, `while`
#### Специальное
`asm`, `assert`, `autofree`, `comptime`, `const`, `embed`, `launch`, `ref`, `sizeof`, `static`, `test`, `volatile`
#### Константы
`true`, `false`, `null`
#### Зарезервировано в Си
Следующие идентификаторы зарезервированы, так как они являются ключевыми словами в C11:
`auto`, `case`, `char`, `default`, `do`, `double`, `extern`, `float`, `inline`, `int`, `long`, `register`, `restrict`, `short`, `signed`, `switch`, `typedef`, `unsigned`, `void`, `_Atomic`, `_Bool`, `_Complex`, `_Generic`, `_Imaginary`, `_Noreturn`, `_Static_assert`, `_Thread_local`
#### Операторы
`and`, `or`
### 17. Взаимодействие с Си
Zen C предлагает два способа взаимодействия с кодом Си: **Доверительные импорты** (Удобно) и **Явный FFI** (Безопасно/Точно).
#### Способ 1: Импорт заголовков
Вы можете импортировать заголовок Си напрямую, используя ключевое слово `import` с расширением `.h`. Это рассматривает заголовок как модуль и предполагает, что все доступные символы существуют.
```zc
//> link: -lm
import "math.h" as c_math;
fn main() {
// Компилятор доверяет корректности; выводит 'cos(...)' напрямую
let x = c_math::cos(3.14159);
}
```
> **Плюсы**: Просто и быстро.
> **Минусы**: Нет проверки типов со стороны Zen C (ошибки перехватываются позже компилятором Си).
#### Метод 2: Явный FFI (Безопасно)
Для строгой проверки типов или когда вы не хотите включать текст заголовка, используйте `extern fn`.
```zc
include // Выводит #include в сгенерированный Си код
// Определите строгую сигнатуру
extern fn printf(fmt: char*, ...) -> c_int;
fn main() {
printf("Hello FFI: %d\n", 42); // Проверено типами Zen C
}
```
> **Плюсы**: Zen C гарантирует совпадение типов.
> **Минусы**: Нужно писать сигнатуры.
#### Разница между `import` и `include`
- **`import "file.h"`**: Регистрирует заголовок как именованный модуль. Включает неявный доступ к символам (например, `file::function()`).
- **`include `**: Просто выводит `#include ` в сгенерированный код C. Не вводит никаких символов в компилятор Zen C; вы должны использовать `extern fn` для их доступа.
---
## Стандартная библиотека
Zen C включает стандартную библиотеку (`std`), охватывающую основную функциональность.
[Просмотрите документацию стандартной библиотеки](docs/std/README.md)
### Ключевые модули
| Модуль | Описание | Docs |
|:---------------------|:---------------------------------------------------|:----------------------------|
| **`std/vec.zc`** | Растущий динамический массив `Vec`. | [Docs](docs/std/vec.md) |
| **`std/string.zc`** | Выделенный в heap тип `String` с поддержкой UTF-8. | [Docs](docs/std/string.md) |
| **`std/queue.zc`** | FIFO очередь (Ring Buffer). | [Docs](docs/std/queue.md) |
| **`std/map.zc`** | Обобщённая хеш-таблица `Map`. | [Docs](docs/std/map.md) |
| **`std/fs.zc`** | Операции файловой системы. | [Docs](docs/std/fs.md) |
| **`std/io.zc`** | Стандартный ввод/вывод (`print`/`println`). | [Docs](docs/std/io.md) |
| **`std/option.zc`** | Опциональные значения (`Some`/`None`). | [Docs](docs/std/option.md) |
| **`std/result.zc`** | Обработка ошибок (`Ok`/`Err`). | [Docs](docs/std/result.md) |
| **`std/path.zc`** | Кроссплатформенная манипуляция путями. | [Docs](docs/std/path.md) |
| **`std/env.zc`** | Переменные окружения процесса. | [Docs](docs/std/env.md) |
| **`std/net.zc`** | TCP сетевое взаимодействие (Sockets). | [Docs](docs/std/net.md) |
| **`std/thread.zc`** | Потоки и синхронизация. | [Docs](docs/std/thread.md) |
| **`std/time.zc`** | Измерение времени и сон. | [Docs](docs/std/time.md) |
| **`std/json.zc`** | Парсинг и сериализация JSON. | [Docs](docs/std/json.md) |
| **`std/stack.zc`** | LIFO стек `Stack`. | [Docs](docs/std/stack.md) |
| **`std/set.zc`** | Обобщённое хеш-множество `Set`. | [Docs](docs/std/set.md) |
| **`std/process.zc`** | Выполнение и управление процессами. | [Docs](docs/std/process.md) |
---
## Инструменты
Zen C предоставляет встроенный языковой сервер и REPL для того, чтобы вам было комфортно программировать на этом ЯП!
### Языковой сервер (LSP)
Языковой сервер Zen C (LSP) поддерживает стандартные функции LSP для интеграции в редактор, предоставляя:
* **Переходы к определению**
* **Нахождения ссылок**
* **Информация при наведении**
* **Автозаполнения:** (имена функций/структур, dot-дополнение для методов/полей)
* **Символы документа** (outline)
* **Справка для сигнатур**
* **Диагностика** (ошибки синтаксиса/семантики)
Чтобы запустить языковой сервер (обычно настраивается в настройках LSP вашего редактора):
```bash
zc lsp
```
Работает это через стандартный I/O (JSON-RPC 2.0).
### REPL
Цикл Read-Eval-Print позволяет вам интерактивно экспериментировать с кодом Zen C.
```bash
zc repl
```
#### Возможности
* **Интерактивное кодирование**: Вводите выражения или операторы для немедленного вычисления.
* **Постоянная история**: Команды сохраняются в `~/.zprep_history`.
* **Стартовый скрипт**: Автоматически загружает команды из `~/.zprep_init.zc`.
#### Команды
| Команда | Описание |
|:----------------|:-----------------------------------------------------------------|
| `:help` | Показать доступные команды. |
| `:reset` | Очистить историю текущей сессии (переменные/функции). |
| `:vars` | Показать активные переменные. |
| `:funcs` | Показать определённые пользователем функции. |
| `:structs` | Показать определённые пользователем структуры. |
| `:imports` | Показать активные импорты. |
| `:history` | Показать историю ввода сессии. |
| `:type ` | Показать тип выражения. |
| `:c ` | Показать сгенерированный код C для оператора. |
| `:time ` | Провести бенчмарк выражения (запускает 1000 итераций). |
| `:edit [n]` | Редактировать команду `n` (по умолчанию: последняя) в `$EDITOR`. |
| `:save ` | Сохранить текущую сессию в файл `.zc`. |
| `:load ` | Загрузить и выполнить файл `.zc` в сессию. |
| `:watch ` | Наблюдать за выражением (переоценивается после каждого ввода). |
| `:unwatch ` | Удалить наблюдение. |
| `:undo` | Удалить последнюю команду из сессии. |
| `:delete ` | Удалить команду с индексом `n`. |
| `:clear` | Очистить экран. |
| `:quit` | Выйти из REPL. |
| `! ` | Запустить команду оболочки (например `!ls`). |
---
## Поддержка компилятора и совместимость
Zen C разработан для работы с большинством компиляторов C11. Некоторые функции полагаются на расширения GNU C, но они часто работают на других компиляторах. Используйте флаг `--cc` для переключения бэкендов.
```bash
zc run app.zc --cc clang
zc run app.zc --cc zig
```
### Статус набора тестов
| Компилятор | Процент успеха | Поддерживаемые функции | Известные ограничения |
|:-----------|:--------------:|:-------------------------------------|:---------------------------------------------------------|
| **GCC** | **100%** | Все функции | Нет. |
| **Clang** | **100%** | Все функции | Нет. |
| **Zig** | **100%** | Все функции | Нет. Использует `zig cc` как drop-in компилятор Си. |
| **TCC** | **~70%** | Базовый синтаксис, обобщения, трейты | Нет `__auto_type`, нет Intel ASM, нет вложенных функций. |
> **Рекомендация:** Используйте **GCC**, **Clang** или **Zig** для производственных сборок. TCC отлично подходит для быстрого прототипирования благодаря его скорости компиляции, но не имеет некоторых продвинутых расширений Си, на которые полагается Zen C для полной поддержки функций.
### Сборка с Zig
Команда `zig cc` Zig предоставляет drop-in замену для GCC/Clang с отличной поддержкой кроссплатформенной компиляции. Чтобы использовать Zig:
```bash
# Компилировать и запустить программу Zen C с Zig
zc run app.zc --cc zig
# Собрать сам компилятор Zen C с Zig
make zig
```
### Взаимодействие с C++
Zen C может генерировать код, совместимый с C++, с флагом `--cpp`, позволяя беспрепятственную интеграцию с библиотеками C++.
```bash
# Прямая компиляция с g++
zc app.zc --cpp
# Или транспилировать для ручной сборки
zc transpile app.zc --cpp
g++ out.c my_cpp_lib.o -o app
```
#### Использование C++ в Zen C
Включите заголовки C++ и используйте сырые блоки для кода C++:
```zc
include
include
raw {
std::vector make_vec(int a, int b) {
return {a, b};
}
}
fn main() {
let v = make_vec(1, 2);
raw { std::cout << "Size: " << v.size() << std::endl; }
}
```
> **Примечание:** Флаг `--cpp` переключает бэкенд на `g++` и выводит совместимый с C++ код (использует `auto` вместо `__auto_type`, перегрузки функций вместо `_Generic` и явные приведения для `void*`).
### Взаимодействие с CUDA
Zen C поддерживает GPU-программирование путём транспиляции в **CUDA C++**. Это позволяет вам использовать мощные функции C++ (шаблоны, constexpr) в ваших ядрах, сохраняя эргономичный синтаксис Zen C.
```bash
# Прямая компиляция с nvcc
zc run app.zc --cuda
# Или транспилировать для ручной сборки
zc transpile app.zc --cuda -o app.cu
nvcc app.cu -o app
```
#### Специфичные для CUDA атрибуты
| Атрибут | Эквивалент CUDA | Описание |
|:----------|:----------------|:-----------------------------------------------------------|
| `@global` | `__global__` | Функция ядра (запускается на GPU, вызывается с хоста). |
| `@device` | `__device__` | Функция устройства (запускается на GPU, вызывается с GPU). |
| `@host` | `__host__` | Функция хоста (явно только для CPU). |
#### Синтаксис запуска ядра
Zen C предоставляет чистый оператор `launch` для вызова ядер CUDA:
```zc
launch kernel_name(args) with {
grid: num_blocks,
block: threads_per_block,
shared_mem: 1024, // Опционально
stream: my_stream // Опционально
};
```
Это транспилируется в: `kernel_name<<>>(args);`
#### Написание ядер CUDA
Используйте синтаксис функции Zen C с `@global` и оператором `launch`:
```zc
import "std/cuda.zc"
@global
fn add_kernel(a: float*, b: float*, c: float*, n: int) {
let i = thread_id();
if i < n {
c[i] = a[i] + b[i];
}
}
fn main() {
def N = 1024;
let d_a = cuda_alloc(N);
let d_b = cuda_alloc(N);
let d_c = cuda_alloc(N);
defer cuda_free(d_a);
defer cuda_free(d_b);
defer cuda_free(d_c);
// ... init data ...
launch add_kernel(d_a, d_b, d_c, N) with {
grid: (N + 255) / 256,
block: 256
};
cuda_sync();
}
```
#### Стандартная библиотека (`std/cuda.zc`)
Zen C предоставляет стандартную библиотеку для общих операций CUDA, чтобы уменьшить использование `raw` блоков:
```zc
import "std/cuda.zc"
// Управление памятью
let d_ptr = cuda_alloc(1024);
cuda_copy_to_device(d_ptr, h_ptr, 1024 * sizeof(float));
defer cuda_free(d_ptr);
// Синхронизация
cuda_sync();
// Индексирование потоков (использование внутри ядер)
let i = thread_id(); // Глобальный индекс
let bid = block_id();
let tid = local_id();
```
> **Примечание:** Флаг `--cuda` устанавливает `nvcc` как компилятор и подразумевает режим `--cpp`. Требует NVIDIA CUDA Toolkit.
### Поддержка C23
Zen C поддерживает современные функции стандарта C23 при использовании совместимого компилятора бэкенда (GCC 14+, Clang 14+, TCC (частичная)).
- **`auto`**: Zen C автоматически отображает вывод типов на стандартный C23 `auto`, если `__STDC_VERSION__ >= 202300L`.
- **`_BitInt(N)`**: Используйте типы `iN` и `uN` (например, `i256`, `u12`, `i24`) для доступа к целым числам произвольной ширины C23.
### Взаимодействие с Objective-C
Zen C может компилировать в Objective-C (`.m`), используя флаг `--objc`, позволяя вам использовать фреймворки Objective-C (такие как Cocoa/Foundation) и синтаксис.
```bash
# Компилировать с clang (или gcc/gnustep)
zc app.zc --objc --cc clang
```
#### Использование Objective-C в Zen C
Используйте `include` для заголовков и `raw` блоки для синтаксиса Objective-C (`@interface`, `[...]`, `@""`).
```zc
//> macos: framework: Foundation
//> linux: cflags: -fconstant-string-class=NSConstantString -D_NATIVE_OBJC_EXCEPTIONS
//> linux: link: -lgnustep-base -lobjc
include
fn main() {
raw {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello from Objective-C!");
[pool drain];
}
println "Zen C works too!";
}
```
> **Примечание:** Интерполяция строк Zen C работает с объектами Objective-C (`id`), вызывая `debugDescription` или `description`.
---
## Участие в разработке
Мы приветствуем ваш вклад! Исправление ошибок, добавление документации или предложение новых функций.
### Как внести свой вклад
1. **Создайте форк репозитория**: стандартный рабочий процесс GitHub.
2. **Создайте ветку функции**: `git checkout -b feature/NewThing`.
3. **Рекомендации по коду**:
* Следуйте существующему стилю Си.
* Убедитесь, что все тесты проходят: `make test`.
* Добавьте новые тесты для вашей функции в `tests/`.
4. **Отправьте запрос на слияние**: Ясно опишите ваши изменения.
### Запуск тестов
Набор тестов — ваш лучший друг!
```bash
# Запустить все тесты (GCC)
make test
# Запустить конкретный тест
./zc run tests/test_match.zc
# Запустить с другим компилятором
./tests/run_tests.sh --cc clang
./tests/run_tests.sh --cc zig
./tests/run_tests.sh --cc tcc
```
### Расширение компилятора
* **Парсер**: `src/parser/` - Рекурсивный парсер спуска.
* **Codegen**: `src/codegen/` - Логика транспилера (Zen C -> GNU C/C11).
* **Стандартная библиотека**: `std/` - Написана на самом Zen C.
---
## Благодарности
Этот проект использует сторонние библиотеки. Полные тексты лицензий можно найти в каталоге `LICENSES/`.
* **[cJSON](https://github.com/DaveGamble/cJSON)** (MIT License): Используется для парсинга JSON и генерации в языковом сервере.
* **[zc-ape](https://github.com/OEvgeny/zc-ape)** (MIT License): Оригинальный порт Actually Portable Executable Zen-C от [Eugene Olonov](https://github.com/OEvgeny).
* **[Cosmopolitan Libc](https://github.com/jart/cosmopolitan)** (ISC License): Основополагающая библиотека, которая делает APE возможной.