Внутренний компонент. Для повседневной работы используй nova CLI. nova-codegen остаётся точкой входа для IDE, CI, прямой отладки codegen — и используется nova-cli как path-зависимость.
Установка и сборка
# Debug-сборка
cargo build --manifest-path compiler-codegen/Cargo.toml
# Release (для bootstrap opt-level=0, без size-оптимизаций)
cargo build --release --manifest-path compiler-codegen/Cargo.toml
# С Z3-бэкендом для контрактов (Plan 33.1)
cargo build --release --manifest-path compiler-codegen/Cargo.toml --features z3-backend
# Rust-уровневые юнит-тесты компилятора
cargo test --manifest-path compiler-codegen/Cargo.toml
Результат: compiler-codegen/target/{debug,release}/nova-codegen[.exe]
Главный поток запускается с 64 MiB стеком — AST-обходы взаимно рекурсивны (expr ↔ block ↔ stmt), type-checker / SCC-purity / SMT-encoder требуют глубокого стека на больших модулях. Default Windows 1 MiB недостаточен.
Минимум зависимостей: clap, anyhow. Собирается с пустым lockfile на любом stable Rust 1.85+.
Коды выхода
| Код | Значение |
|---|---|
0 | Успех |
1 | Ошибка (parse fail, type-check fail, codegen fail, runtime fail, тесты упали) |
В отличие от nova, nova-codegen использует бинарный exit-режим (0/1) — без разделения usage-ошибки и диагностики.
nova-codegen check
Type-check файла без запуска.
nova-codegen check FILE
Pipeline:
read_file(path)parser::parse(&src)→ ASTcheck_module_path— D78 path/module enforcementtypes::check_module→ type-check + effect-inference- Печатает
ok: {} parsed and checked
При ошибке — рендерится через Diagnostic::render с line:col и underline'ом исходника.
nova-codegen run
Type-check + интерпретировать (вызывается fn main).
nova-codegen run FILE
Pipeline:
- parse + path-check + type-check
types::annotate_map_literals— аннотация[k: v]-литералов inferred K/Vdesugar::desugar_module— десугаринг map-литералов вwith_capacity+@insertinterp::Interpreter::new()→load_module→run_main
Treewalk-интерпретатор имеет паритет с codegen-бэкендом — те же эффекты, handler'ы, structured concurrency, контракты, defer, channels.
nova-codegen test
Запустить test "..." { ... } блоки в файле через интерпретатор.
nova-codegen test FILE
Pipeline: parse → path-check → annotate_map_literals → desugar → interp::run_tests → tests: N passed, N failed.
Exit 1 если хотя бы один тест fail'нул; печатает имена failed-тестов.
Это интерпретаторный тест-режим (быстро, без C-pipeline). Для проверки codegen-pipeline используй test-build или test-all.
nova-codegen compile
Скомпилировать .nv в .c (без линковки).
nova-codegen compile FILE [-o OUTPUT] [--no-annotate-source] [--no-lint]
| Флаг | По умолчанию | Описание |
|---|---|---|
FILE | — | .nv файл. |
-o OUTPUT | <name>.c рядом с source | Путь к выходному .c. |
--no-annotate-source | off (аннотации включены) | Не вставлять /* SRC: ... */ комментарии — для compact-вывода. |
--no-lint | off (lint включён) | Отключить lint-проверки. |
Pipeline:
- parse + path-check + type-check
annotate_map_literals+desugar_moduletypes::infer_effects— D28 effect-inference для private fnlints::lint_module(если lint включён)CEmitter::new()+set_source_for_annotations(src)set_proven_contracts— selective contract stripping (Plan 33.3, true zero-cost)emit_module→ C-код + warnings- Запись в output path
SRC-аннотации (/* SRC: ... */) — сопоставляют C-строки с Nova-исходником. По умолчанию включены; удобны для .c-отладки.
nova-codegen emit-runtime-stubs
Регенерация std/runtime/string.nv и std/runtime/math.nv из runtime_registry.rs (Plan 13).
nova-codegen emit-runtime-stubs [--root PATH] [--check]
| Флаг | По умолчанию | Описание |
|---|---|---|
--root PATH | . (CWD) | Корень репозитория (где std/runtime/). |
--check | off | Только сравнить; exit 1 при diff (CI / pre-commit guard). |
Workflow добавления новой runtime fn (например f64.@cbrt):
- Добавить
RuntimeFn { ... }вsrc/codegen/runtime_registry.rs. - Реализовать в
nova_rt/<module>.c(или wrapper к libc). - Регенерация:
nova regen-runtime(илиnova-codegen emit-runtime-stubs --root .). - Коммит всех трёх (registry +
.c+.nv).
--check нормализует line endings (CRLF → LF) перед сравнением. Сгенерированные файлы охраняются nova regen-runtime --check в CI — не править вручную.
nova-codegen dump-runtime
Sanity-print registry runtime-функций (Plan 13) — для аудита расхождений registry vs реальных C-сигнатур в nova_rt/.
nova-codegen dump-runtime
Nova runtime registry: N function(s) total.
=== <module> (N fns) ===
<receiver> [mut] <.|@><name>(<params>) -> <return-ty> [c: <c-name>]
...
. = static fn (Type.fn). @ = instance method (obj.@fn).
nova-codegen test-build
Cross-platform per-file test runner (Plan 24): компиляция одного .nv в .exe и проверка EXPECT-маркеров (D89).
nova-codegen test-build FILE [--mode dev|release] [--toolchain auto|clang|msvc|gcc]
[--vcvars PATH] [--clang PATH]
[--cg-include PATH] [--rt-dir PATH] [--tmp-dir PATH]
[--display NAME] [--keep-artifacts]
[--timeout SECS] [--gc boehm|malloc]
| Флаг | По умолчанию | Описание |
|---|---|---|
FILE | — | .nv test-файл. |
--mode | dev | dev или release. |
--toolchain | auto | auto, clang, msvc, gcc. |
--vcvars PATH | auto через vswhere | Путь к vcvars64.bat (Windows). |
--clang PATH | auto detect | Путь к clang.exe. |
--cg-include PATH | <cwd>/compiler-codegen | Путь к compiler-codegen/ для include nova_rt/. |
--rt-dir PATH | <cwd>/compiler-codegen/nova_rt | Runtime sources. |
--tmp-dir PATH | $TEMP/nova_tests или $TMPDIR/nova_tests | Tmp директория для .c/.exe/.obj. |
--display NAME | basename | Override display-name в выводе. |
--keep-artifacts | off | Не удалять артефакты. |
--timeout SECS | 60 | Per-test timeout. |
--gc | boehm | boehm или malloc. |
Pipeline: detect toolchain → detect/build libuv → compile .nv → .c → .exe → run → проверить EXPECT-маркеры.
Output format: <STATUS:14> <display> # <detail>
EXPECT-маркеры (D89):
// EXPECT: <line>— точное совпадение stdout-строки// EXPECT_STDERR: <line>— для stderr// EXPECT_COMPILE_ERROR: <substring>— должен fail при компиляции// EXPECT_RUNTIME_ERROR: <substring>— panic с подстрокой// REQUIRES_SMT_BACKEND— пропуск если SMT недоступен
nova-codegen test-all
Batch test runner (Plan 24): рекурсивный прогон всех .nv в --tests-dir. Используется как движок для nova test.
nova-codegen test-all [--tests-dir PATH] [--stdlib-dir PATH] [--include-stdlib]
[--filter SUBSTR] [--mode dev|release]
[--toolchain auto|clang|msvc|gcc]
[--vcvars PATH] [--clang PATH]
[--cg-include PATH] [--rt-dir PATH] [--tmp-dir PATH]
[--keep-artifacts] [--timeout SECS] [--jobs N]
[--format text|json|tap] [-v|-q]
[--results-file PATH] [--rerun-failed]
[--retries N] [--gc boehm|malloc]
| Флаг | По умолчанию | Описание |
|---|---|---|
--tests-dir PATH | nova_tests | Корень тестового корпуса. |
--stdlib-dir PATH | std | Корень std/ (если --include-stdlib). |
--include-stdlib | off | Включить std/* файлы. |
--filter SUBSTR | — | Filter по display-name. |
--mode | dev | См. test-build. |
--toolchain | auto | |
--vcvars, --clang | auto | |
--cg-include, --rt-dir | вычисляются из CWD | |
--tmp-dir | $TEMP/nova_tests или эквивалент | |
--keep-artifacts | off | |
--timeout | 60 | Per-test timeout. |
--jobs N | 0 (= num_cpus) | Параллельные worker'ы. |
--format | text | text, json, tap. |
-v, --verbose | off | Output PASS-тестов. |
-q, --quiet | off | Только FAIL + summary. |
--results-file PATH | — | Файл last-results.json. |
--rerun-failed | off | Перезапустить только failed/timeout из results file. |
--retries N | 0 | Retry на transient AV/race fail'ах (CI default 2). |
--gc | boehm | См. test-build. |
Информационные сообщения (toolchain, libuv) — в stderr. Per-test events и summary — в stdout.
Примечание: --list, --filter-from, --shuffle, --skip, --mono-depth поддерживаются только через nova test.
Переменные окружения
| Переменная | Эффект |
|---|---|
NOVA_NO_CACHE=1 | Отключить SMT-кэш контрактов (Plan 33.3). |
NOVA_PERF_TIMER=1 | Включить __PERF__ маркеры в компиляторе (per-pass timing). |
NOVA_MONO_DEPTH=N | Лимит monomorphization-инстанциаций (default 500). |
NOVA_DEBUG_MONO=1 | Verbose debug-print mono-instances. |
NOVA_SMT_BACKEND=trivial|z3 | Override SMT-backend для контрактов. |
NOVA_CACHE_DIR=PATH | Override директории SMT proof cache (default <cwd>/target/). |
NOVA_CLANG=PATH | Override clang.exe для test-build/test-all. |
NOVA_GCC=PATH | Override пути к gcc. |
NOVA_VCVARS=PATH | Override vcvars64.bat (Windows MSVC). |
NOVA_MARCH_NATIVE=1 | Включить -march=native (release builds; non-portable binary). |
NOVA_GC_LIB_DIR=PATH | Override директории libgc.a / gc.lib (Boehm). |
NOVA_GC_INCLUDE_DIR=PATH | Override include path для gc.h. |
VCPKG_ROOT=PATH | Корень vcpkg (для авто-резолва libuv / libz3). |
CC=name | Fallback C compiler (POSIX). |
NOVA_VERSION=N.M.K | Текущая версия для deprecation diagnostics (Plan 45). |
NOVA_FEATURES=f1,f2 | Cfg feature-set (Plan 42.12). |
NOVA_TARGET_OS=name | Override target_os для cfg-resolve. |
TEMP (Windows) | Tmp директория для build/test artifacts. |
TMPDIR (Unix) | То же. |
PATH | Поиск clang/gcc/cl/vswhere. |
ProgramFiles(x86) | Поиск vswhere для MSVC auto-detect. |
Cargo features
| Feature | Описание |
|---|---|
| (default) | TrivialBackend SMT (reflexive ensures), без external dependencies. |
z3-backend | Подключает libz3 через vcpkg (Plan 33.1). FFI bindings — собственные в src/verify/backend/z3_ffi.rs (без z3/z3-sys crate'ов). Linkage контролируется через build.rs + vcpkg.json. |
# Сборка с Z3:
cargo build --release --features z3-backend
# Запуск тестов с Z3:
NOVA_SMT_BACKEND=z3 nova test
Library API (nova_codegen)
nova-cli использует nova-codegen как path-зависимость и работает с library-API напрямую (без subprocess). Публичные модули из lib.rs:
| Модуль | Что |
|---|---|
argbind | Named/positional arg binding (Plan 46 / D102). |
ast | Типы AST: Module, Item, Expr, Stmt, Pattern, … |
callnorm | Call-site normalization для named params. |
codegen | C-бэкенд: CEmitter::emit_module, runtime_registry::all, … |
desugar | Desugar map-литералов, for-in, и прочих сахаров. |
diag | Структурированные диагностики (Diagnostic, Span, byte_to_line_col). |
doc | Plan 45 — DocModel, рендеры, MCP-server. |
imports | Plan 35 R31 — cross-file resolver (resolve_imports_inline). |
interp | Treewalk-интерпретатор (Interpreter::new / load_module / run_main / run_tests). |
lexer | Токенизация: lex(&src) -> Vec<Token>. |
lints | D-rule based lints (lint_module). |
manifest | nova.toml + D78 path/module enforcement. |
parser | Recursive-descent parser (parse(&src) -> Result<Module, Diagnostic>). |
perf_timer | NOVA_PERF_TIMER instrumentation. |
test_runner | Test discovery + parallel execution + toolchain detect. |
types | Type-checker + effect inference (check_module, infer_effects, annotate_map_literals). |
verify | SMT contracts integration (TrivialBackend, Z3Backend под feature). |
Re-exports: Diagnostic, Span напрямую из nova_codegen::*.
Внутренняя архитектура
src/
lexer/ токенизация
parser/ recursive-descent parser
ast/ типы AST
types/ type checker + effect inference + lints
interp/ treewalk interpreter
codegen/ C-бэкенд
emit_c.rs основной codegen (~20k LOC)
runtime_registry.rs source-of-truth для std/runtime/*.nv stubs
imports.rs Plan 35 R31: cross-file resolver
diag/ структурированные ошибки (с FileId для cross-file)
manifest.rs nova.toml + D78 path enforcement
lints.rs D-rule based lints
test_runner.rs test discovery + parallel execution
verify/ contracts SMT (TrivialBackend + Z3 опционально)
doc/ Plan 45 nova doc (parser, renderer, MCP)
desugar.rs desugaring passes
argbind.rs named-params binding (Plan 46)
callnorm.rs call-site normalization
perf_timer.rs NOVA_PERF_TIMER markers
lib.rs re-exports
main.rs CLI dispatch (~664 LOC)
Cross-file resolver (Plan 35 R31)
imports::resolve_imports_inline — shared между nova check, nova build, nova test:
- DFS с cycle detection (
in_progress+visitedмножества). - Selective import
X.{A, B}(синтаксис; bootstrap MVP не enforce'ит filter). export import X.{A}re-export.- Auto-import
std/prelude.nv(R27).
Folder-modules (Plan 42)
Module = single-file X.nv ИЛИ folder X/ с peers (Go-style):
manifest::resolve_module_paths→Vec<PathBuf>, alphabetical sort для deterministic build.*_test.nvpeers фильтруются если!include_test_peers.X.nv+X/с direct.nv→ ambiguous error.internal/<…>path-protection — import только из parent's descendants._module.nvconvention для module-level#forbid/#cfg/#doc.
D78 path/module enforcement
Если файл лежит внутри пакета (nova.toml в parent dirs), компилятор проверяет соответствие module X.Y.Z ↔ filesystem path. Standalone .nv без nova.toml проверку проходят.
Effect inference (D28)
types::infer_effects добавляет Fail в effect-row private fn, если тело содержит throw и нет явного Fail. Public fn — explicit only (D28: «public API не должно неявно throw'ить»).
Plan 33.3 contract stripping (Ф.9.9)
CEmitter::set_proven_contracts selectively strip'ает body proven контрактов в codegen (true zero-cost даже в debug). SMT-доказанные requires/ensures/invariant не эмитятся как runtime assertions.
Runtime (nova_rt/)
C-исходники линкуются в каждый .exe. Минимум 3 .c:
| Файл | Что |
|---|---|
alloc.c (или alloc_boehm.c, alloc_rc.c) | Allocator (Boehm GC default с Plan 27). |
effects.c | Handler-стек (D61), nova_interrupt / nova_interrupt_ptr. |
fibers.c | Shim над minicoro.h + structured concurrency (Plan 44.5). |
Header-only:
| Header | Что |
|---|---|
array.h | NovaArray_<T>, NovaOpt_<T> auto-gen helpers. |
cast.h | D54 narrow casts (saturation, wrap-around semantics). |
effects.h | NovaThrowKind, nova_throw_cancel, Handler[E, IRT] API. |
fibers.h | nova_spawn, nova_supervised, nova_cancel_*, M:N runtime. |
channels.h | Channel[T] mpsc (Plan 44.1), select waiter. |
sync.h | C11 atomics + mutex для channel hardening. |
minicoro.h | Vendored stackful coroutines (version-pinned, не патчим). |
nova_rt.h | Единый include — nova_str_cmp/lt/le/gt/ge byte-wise compare и пр. |
Build scripts в compiler-codegen/: build_c.bat / build_c.ps1 / build_c.sh, vcpkg.json / vcpkg_installed/ (vendored libuv + libz3), build.rs (feature-flag wiring).