Фундаментальные принципы, философия и обязательства
TextToCAD Scripting Language
Язык, который описывает ровно то, что нужно,
гарантирует ровно то, что обещает.
Этот документ фиксирует фундаментальные принципы, философию и обязательства языка TCSL. Манифест не заменяет спецификацию — он объясняет, почему спецификация устроена именно так. Каждое решение в грамматике, системе типов и архитектуре парсера восходит к принципам, изложенным здесь. Когда возникает неоднозначность или конфликт между возможными решениями, манифест служит арбитром.
Между замыслом конструктора и трёхмерной моделью в FreeCAD лежит пропасть. Традиционно её заполняют двумя способами: ручным моделированием (медленно, не параметрично) или программированием на Python (мощно, но требует квалификации разработчика). TCSL создан, чтобы эту пропасть мог преодолеть третий участник — языковая модель, генерирующая код по текстовому описанию изделия.
TCSL — это контракт между человеком, машиной и геометрическим ядром. Человек задаёт параметры. Машина вычисляет производные и строит геометрию. Ядро гарантирует результат. Контракт работает, только если каждая сторона может проверить свою часть до передачи следующей. Именно поэтому существует парсер — независимый арбитр, проверяющий контракт за миллисекунды, без запуска FreeCAD.
inputlet и строит геометриюЧисло без единицы — не длина. 100 — это не 100 mm, а безразмерный скаляр. TCSL не позволяет складывать миллиметры с градусами, умножать объём на длину и получать несуществующую размерность L⁴. Система типов замкнута на диапазоне L⁰–L³ плюс отдельная ось углов, и эта замкнутость проверяется до того, как хоть один полигон будет построен.
Это не педантичность — это защита от класса ошибок, которые невозможно обнаружить визуально в готовой модели. Деталь, смещённая на 100 вместо 100 мм, выглядит правильно до тех пор, пока не попадает в сборку.
Программа TCSL движется в одном направлении: от параметров к геометрии, от геометрии к экспорту. Зоны INPUT → LET → GEOMETRY → EXPORT следуют строго в этом порядке, и переход необратим. Это не ограничение выразительности — это архитектурное решение, отражающее реальный процесс проектирования.
INPUT — это то, что меняет заказчик. LET — это то, что вычисляет инженер. GEOMETRY — это то, что строит станок. EXPORT — это то, что считает калькулятор. Смешивать эти ответственности значит терять возможность автоматизировать каждую из них по отдельности.
Если параметр total_width изменился, все зависимые от него значения обновляются автоматически. В TCSL нет способа «забыть» обновить производный параметр, потому что производные параметры — это формулы, а не числа. let inner_width = total_width - 2 * board — это живая связь, не мёртвая запись.
Разделение на input (литералы, переопределяемые извне) и let (формулы, вычисляемые автоматически) гарантирует, что GUI-конфигуратор показывает ровно то, что нужно менять, и скрывает то, что менять нельзя.
TCSL — однострочный язык. Каждая инструкция занимает ровно одну строку. Продолжение строки не поддерживается. Конвейер |> — единственный способ выразить сложную операцию, и он остаётся на той же строке.
Это сознательная жертва компактности ради однозначности. Парсер синхронизируется по границе строки. LLM генерирует код построчно. Человек читает код построчно. Ошибка локализуется на одну строку. Диагностика указывает на одну строку.
Переменная в TCSL — это не просто адрес в памяти. Имя corpus_left_side описывает деталь для человека. Имя Bok_LDSP16mm_1 после export ... as описывает ту же деталь для калькулятора себестоимости. Оба имени живут в одной строке, и оба проверяются парсером.
TCSL связывает мир инженерного проектирования (читаемые имена переменных) с миром производственного учёта (кодифицированные имена деталей) через единственный синтаксический мост — конструкцию export ... as.
TCSL определяет 32 кода диагностики не потому, что язык сложен, а потому, что каждая ошибка заслуживает собственного объяснения. TCSL_E015 — не «type error», а «размерность результата выходит за диапазон L⁰–L³». TCSL_R008 — не «runtime error», а «деление на ноль». Каждый код — это адрес в спецификации, по которому можно найти объяснение, пример и способ исправления.
Парсер обязан обнаружить всё, что может обнаружить без запуска геометрического ядра. Две ошибки (R005 — пустой результат селектора, R006 — несовпадение типа при runtime-переопределении) остаются за парсером осознанно — они требуют выполнения. Всё остальное проверяется статически.
TCSL спроектирован так, чтобы его мог генерировать LLM пошагово, без возвратов. Четыре зоны соответствуют четырём фазам генерации: сначала базовые параметры (LLM извлекает из ТЗ), затем формулы (LLM вычисляет зависимости), затем геометрия (LLM строит детали), затем экспорт (LLM назначает имена для калькулятора).
Отсутствие пользовательских функций, вложенных блоков, условных конструкций и циклов — не недостаток, а требование. Каждая из этих конструкций увеличивает пространство состояний, в котором LLM может ошибиться. TCSL сужает это пространство до минимума, достаточного для описания корпусной мебели.
Между генерацией кода и его исполнением стоит парсер. Он работает за миллисекунды, не требует FreeCAD, не потребляет GPU-токены и не создаёт файлов. Его единственная задача — сказать «да» или «нет, и вот почему».
Парсер проверяет всё, что можно проверить без геометрии: лексику, синтаксис, порядок зон, размерную алгебру, совместимость pipeline-типов, арность операций, уникальность экспортов, положительность параметров конструкторов, целочисленность счётчиков, деление на ноль. Это 30 проверок из 32 — парсер покрывает 94% спецификации.
Поведение парсера определяется спецификацией v1.5, а не реализацией. Если реализация расходится со спецификацией — это баг реализации, не спецификации. EBNF-грамматика v1.5 с 62 продукциями и 25 семантическими ограничениями — это формальный контракт, по которому можно написать альтернативную реализацию и получить идентичное поведение.
Парсер является reference implementation, но не эталоном. Эталон — текст спецификации. Парсер — его исполняемое воплощение.
TCSL v1.5 содержит 62 грамматических правила, 23 функции, 5 перечислений, 17 единиц измерения и 32 кода ошибок. Это немного. Это достаточно для описания корпусной мебели произвольной сложности. Каждый элемент языка должен оправдать своё существование задачей, которую невозможно решить без него.
Предложение о добавлении новой конструкции должно ответить на три вопроса: какую задачу невозможно решить существующими средствами, насколько это усложнит генерацию LLM и насколько это усложнит диагностику ошибок. Если ответ на любой из трёх вопросов неудовлетворителен — конструкция не добавляется.
Парсер TCSL работает на стандартной библиотеке Python 3.11+ и ни на чём больше. Это гарантирует, что парсер можно запустить в любом окружении, где есть Python: CI-сервер, Docker-контейнер, локальная машина разработчика, Jupyter notebook, облачная функция. Зависимость от внешних библиотек — это долг, который рано или поздно приходится платить обновлениями, конфликтами версий и потерей воспроизводимости.
Лексер отвечает за символы и токены. Парсер отвечает за структуру и грамматику. Анализатор отвечает за типы и семантику. Каждая фаза получает выход предыдущей и не имеет обратных зависимостей. Это позволяет тестировать каждую фазу изолированно, заменять реализацию фазы без влияния на остальные и отлаживать проблемы, начиная с самого низкого уровня.
Парсер обязан собрать максимальное количество ошибок за один проход. Обнаружив ошибку на строке 5, он синхронизируется по границе строки и продолжает со строки 6. Семантический анализатор запускается даже при наличии синтаксических ошибок — на тех частях AST, которые были успешно разобраны. Это критично для LLM-агента, который получает все ошибки одним пакетом и исправляет их одной итерацией, а не серией «исправил одну → обнаружил следующую».
Каждый токен, каждый узел AST, каждая диагностика содержат Span — точное указание на файл, строку, начальный и конечный столбец. Это не роскошь, а требование для трёх потребителей: IDE (подчёркивание ошибки), CI (машинно-читаемый отчёт) и LLM (автоматическое исправление по позиции).
Одинаковый входной файл всегда порождает одинаковый AST, одинаковую таблицу символов и одинаковый список диагностик. Порядок диагностик определяется позицией в файле, не порядком обхода AST. Это позволяет использовать snapshot-тесты и гарантировать воспроизводимость в CI.
TCSL осознанно не поддерживает и не будет поддерживать:
Каждая функция TCSL — встроенная, с фиксированной сигнатурой и семантикой. Пользовательские функции вводят абстракцию, требующую системы типов для возвращаемых значений, правил области видимости и механизма вызова. Для DSL корпусной мебели эта сложность не оправдана.
if/else и for/while превращают декларативное описание в императивную программу с ветвлениями, которые LLM должен предвидеть. Паттерны (linear_pattern, circular_pattern) покрывают потребность в повторении без общего механизма циклов.
Все идентификаторы живут в единой плоской таблице символов. Вложенные области видимости (блоки, замыкания) усложняют разрешение имён и делают код менее предсказуемым для LLM.
TCSL оперирует числами, единицами, идентификаторами и перечислениями. Строки не нужны: имена тегов и as-идентификаторы — это идентификаторы, подчиняющиеся тем же лексическим правилам.
Каждый файл .tcsl — самодостаточная единица. Зависимости между файлами создают граф, который нужно разрешать, версионировать и кэшировать. Для описания одного изделия это избыточно.
Эти ограничения — не технический долг. Это архитектурные решения, защищающие простоту языка. Если задача требует конструкций за пределами TCSL, решение — не расширять TCSL, а использовать Python-обёртку вокруг сгенерированного кода.
TCSL читается как спецификация изделия. Имена переменных осмысленны, комментарии пояснительны, структура последовательна. Программу на TCSL можно показать коллеге, не знакомому с языком, и он поймёт, что описано.
TCSL генерируется за один проход, без возвратов, с предсказуемой структурой. Четыре зоны соответствуют четырём шагам промта. Ошибки возвращаются с точными позициями и кодами, пригодными для автоматического исправления.
Каждая экспортированная деталь имеет имя, из которого извлекается элемент, материал, толщина и порядковый номер. Формат имени проверяется парсером (предупреждение W001), а не постфактум при импорте в калькулятор.
AST типизирован, таблица символов полна, все проверки выполнены. Транспилятор может доверять входным данным и сосредоточиться на генерации Python-кода, не дублируя логику валидации.
Проверка занимает миллисекунды, exit code однозначен (0 — нет ошибок, 1 — есть ошибки), вывод доступен в текстовом и JSON-формате. TCSL-валидация встраивается в pipeline так же естественно, как линтер или тайпчекер.
TCSL версионируется по схеме <major>.<minor>. Minor-версия (1.4 → 1.5) добавляет новые конструкции, коды ошибок, уточняет семантику. Обратно совместима: программа, валидная в v1.4, остаётся валидной в v1.5 (за исключением исправлений ошибок спецификации). Major-версия (1.x → 2.0) допускает несовместимые изменения: удаление конструкций, изменение семантики существующих, реструктуризацию зон.
Каждое изменение спецификации должно пройти через четыре фильтра:
Необходимость. Какую реальную задачу невозможно решить текущими средствами?
Генерируемость. Насколько усложнится генерация LLM? Увеличится ли число ошибок?
Диагностируемость. Можно ли проверить новую конструкцию статически? Какие коды ошибок добавляются?
Обратная совместимость. Сломает ли изменение существующие программы?
Если любой из фильтров даёт отрицательный ответ — изменение откладывается или отклоняется.
TCSL — это не язык программирования общего назначения. Это инструмент для одной задачи: превратить текстовое описание мебельного изделия в параметрическую 3D-модель с именами, пригодными для производственного учёта. Каждое решение в языке — от размерной типизации до четырёхзонной структуры, от запрета пользовательских функций до обязательных единиц измерения — подчинено этой задаче.
Простота TCSL — не начальное состояние, из которого язык будет «расти». Это целевое свойство, которое нужно защищать при каждом изменении. Язык, который может описать всё, не может гарантировать ничего. Язык, который описывает ровно то, что нужно, гарантирует ровно то, что обещает.
TCSL описывает не мебель, а физические объекты. Правила отрасли подключаются модульно — ядро остаётся единым
Манифест TCSL v1.0 · Принят 18 марта 2026 · CC BY-SA 4.0
Вопросы: texttocad@ya.ru