[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 **Современная эргономика. Никаких накладных расходов. Чистый Си.** [![Build Status](https://img.shields.io/badge/build-passing-brightgreen)]() [![License](https://img.shields.io/badge/license-MIT-blue)]() [![Version](https://img.shields.io/github/v/release/z-libs/Zen-C?label=version&color=orange)]() [![Platform](https://img.shields.io/badge/platform-linux-lightgrey)]() *Пишите как на высокоуровневом языке, запускайте как Си.*
--- ## Обзор **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 возможной.