
Я Сделал Это
Почему вообще
Всё началось с мечты — написать свой собственный язык программирования. Я смотрел кучу роликов на YouTube, пытался что-то понять, но эти жалкие попытки ни к чему не приводили. В теории я знал как устроен интерпретатор — лексер, парсер, AST. Но как воплотить это в реальный код — не понимал совсем.
Потом я наткнулся на один ролик который дал мне надежду. Я вспомнил что DeepSeek неплохо пишет код и решил попробовать — первый Python проект заработал. Я был на седьмом небе от счастья.
Но тот проект был сырой и недоделанный. А когда пытаешься сделать на нём что-то серьёзное — DeepSeek выдавал код полный ошибок. Я фиксил один баг, появлялись три новых. Стало ясно что просто просить AI написать язык — не работает.
Однажды я снова сидел на YouTube и наткнулся на видео с канала WeaklyHow — он создавал свой язык программирования с помощью нейросетей. Видео было на английском, но я смотрел просто так — контекст был понятен и без перевода.
И вот в этом видео была нейросеть которая меня зацепила — Claude AI. Я открыл его в браузере, описал что хочу, и попытался создать проект. Собрал в Termux — и он заработал. Без лагов, без багов, с первого раза.
Я не мог поверить. После всех мучений с DeepSeek это было как день и ночь.
Но это был ещё не KITE.
После глотка свежего воздуха с Claude AI я стал пробовать разные подходы — компиляцию и интерпретацию, функциональное программирование. Всё это я уже делал на C, для лучшей производительности и скорости.
Я устроил настоящий марафон в поисках лучшего синтаксиса и функционала для полноценного проекта. Пробовал, выбрасывал, начинал заново. Искал то самое сочетание — минимальный синтаксис, максимум возможностей.
И вот 21 марта 2026 года он родился — KITE.
По факту я его вайбкодил — но KITE не коммерческий проект. Вы можете делать с ним что душе угодно: сделать свой язык на его основе, улучшить его, или наоборот сломать всё что я построил. Исходники открытые, MIT лицензия — берите и творите.
Синтаксис — осознанные решения
Первое что бросается в глаза — KITE не похож ни на C, ни на Python, ни на Rust.
set name = "мир" say("Привет, ${name}!") def factorial(n): when n <= 1: give 1 end give n * factorial(n - 1) end loop for i in range(10): say("${i}! = ${factorial(i)}") end
Несколько осознанных решений:
set вместо var/let — короче, читается как "установить значение". Переприсваивание без set вызывает ошибку — нельзя случайно создать переменную опечаткой.
when/orwhen/else вместо if/elif/else — when читается естественно: "когда x > 0 — делай это".
give вместо return — возвращаешь значение, "отдаёшь" его.
loop while и loop for — все циклы начинаются одинаково, нет путаницы.
Нет точек с запятой — блоки через двоеточие и end, как в Ruby.
Как устроен интерпретатор
Классическая трёхэтапная архитектура: лексер → парсер → интерпретатор.
Лексер (lexer.c)
Лексер превращает исходный текст в поток токенов. Например:
set x = 42 + 8
Превращается в:
TK_SET TK_IDENT("x") TK_ASSIGN TK_NUM(42) TK_PLUS TK_NUM(8)
Интересная деталь — интерполяция строк ${} обрабатывается прямо в лексере. Строка "Привет, ${name}!" разбивается на маркеры внутри токена TK_FMTSTR. Потом парсер разбирает выражение внутри ${} как обычный под-лексер.
Парсер (parser.c)
Рекурсивный descent-парсер строит AST (Abstract Syntax Tree). Каждый узел дерева — структура Node с полем kind:
typedef enum { ND_NUM, ND_STR, ND_FMTSTR, ND_BOOL, ND_NIL, ND_SET, ND_ASSIGN, ND_BINOP, ND_UNOP, ND_CALL, ND_INDEX, ND_PROP, ND_DEF, ND_WHEN, ND_LOOP_WHILE, ND_LOOP_FOR, ND_DO, ND_OBJ, ND_GIVE, ND_BREAK, ND_NEXT, /* ... */ } NKind;
Для выражений используется классическая иерархия приоритетов:
assign → or → and → not → cmp → add → mul → pow → unary → postfix → primary
Интерпретатор (interp.c)
Tree-walking интерпретатор — просто рекурсивно обходит AST:
Value *eval(Interp *ip, Node *n, Env *env) { switch (n->kind) { case ND_NUM: return val_num(n->num); case ND_SET: { Value *v = eval(ip, n->set.val, env); env_def(env, n->set.name, v); return val_nil(); } /* ... */ } }
Управление памятью
Вместо GC — reference counting. Каждое значение имеет счётчик ссылок:
struct Value { VType type; int refs; /* счётчик ссылок */ union { double num; char *str; KiteList *list; /* ... */ }; };
val_ref() увеличивает счётчик, val_unref() уменьшает — и освобождает если достиг нуля. Просто и предсказуемо, без пауз сборщика мусора.
Замыкания
Замыкания в KITE работают через лексическое окружение. Каждая функция хранит ссылку на Env где была создана:
typedef struct KiteFn { char *name; char **params; int nparams; Node *body; Env *closure; /* ← захваченное окружение */ int refs; } KiteFn;
def make_counter(start): set count = start def inc(): count += 1 give count end give inc end set c = make_counter(0) say(c()) # 1 say(c()) # 2 say(c()) # 3
ООП
ООП реализован через ключевое слово obj. Под капотом — структура KiteClass с env методов и KiteInstance с env полей:
obj Animal: set name = nil def init(self, name): self.name = name end def speak(self): say("${self.name} издаёт звук") end end obj Dog extends Animal: set _tricks = 0 # приватное поле (_) def learn(self): self._tricks += 1 end def speak(self): super.speak(self) # вызов родителя say("${self.name}: Гав!") end end set d = Dog.new("Шарик") d.learn() d.speak() say(d is Dog) # true say(d is Animal) # true
Инкапсуляция — поля с _ в начале доступны только внутри методов класса. Попытка обратиться снаружи бросает AccessError.
Обработка ошибок
do: set data = file_read("config.txt") err IOError: say("Файл не найден, создаём...") file_create("config.txt") err: say("Неожиданная ошибка: ${err_msg}") end
Типы ошибок: ZeroDivisionError, NameError, IndexError, TypeError, IOError, AccessError, RuntimeError.
Стандартные библиотеки
use math # tan, log2, clamp, lerp, E, INF... use rand # rand(), rand_choice(), rand_shuffle() use string # str_pad_left, str_count, str_rev... use list # list_sum, list_zip, list_group, list_any... use io # file_read, file_write, file_lines... use os # os_env, os_shell, os_time...
Запуск на Android (Termux)
Это, пожалуй, самая приятная часть. KITE компилируется и работает прямо на телефоне:
pkg install clang make tar -xzf kite-lang.tar.gz cd kite-lang make CC=clang cp kite $PREFIX/bin/kite kite --version # kite 1.2.0
После этого можно писать программы в micro или vim прямо на телефоне. Подсветка синтаксиса для micro тоже есть в репозитории.
Что внутри (статистика)
Файл | Строк | Роль |
|---|---|---|
| ~250 | Типы, AST, прототипы |
| ~200 | Токенизатор |
| ~700 | Рекурсивный парсер |
| ~300 | Значения, refcount, env |
| ~1600 | Интерпретатор + builtins |
| ~120 | Точка входа, REPL |
Итого | ~3200 |
Что дальше
Байт-код компилятор и VM вместо tree-walking
Модульная система (
use mymodule)Многострочные строки
Форматированный вывод
Попробовать
git clone https://github.com/svetozargashtold7-png/kite-lang cd kite-lang make && ./kite
Буду рад вопросам и критике в комментариях. Если захочешь поучаствовать в разработке — PR приветствуются!
