Внутренний компонент. Для повседневной работы используй 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:

  1. read_file(path)
  2. parser::parse(&src) → AST
  3. check_module_path — D78 path/module enforcement
  4. types::check_module → type-check + effect-inference
  5. Печатает ok: {} parsed and checked

При ошибке — рендерится через Diagnostic::render с line:col и underline'ом исходника.


nova-codegen run

Type-check + интерпретировать (вызывается fn main).

nova-codegen run FILE

Pipeline:

  1. parse + path-check + type-check
  2. types::annotate_map_literals — аннотация [k: v]-литералов inferred K/V
  3. desugar::desugar_module — десугаринг map-литералов в with_capacity + @insert
  4. interp::Interpreter::new()load_modulerun_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_teststests: 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-sourceoff (аннотации включены)Не вставлять /* SRC: ... */ комментарии — для compact-вывода.
--no-lintoff (lint включён)Отключить lint-проверки.

Pipeline:

  1. parse + path-check + type-check
  2. annotate_map_literals + desugar_module
  3. types::infer_effects — D28 effect-inference для private fn
  4. lints::lint_module (если lint включён)
  5. CEmitter::new() + set_source_for_annotations(src)
  6. set_proven_contracts — selective contract stripping (Plan 33.3, true zero-cost)
  7. emit_module → C-код + warnings
  8. Запись в 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/).
--checkoffТолько сравнить; exit 1 при diff (CI / pre-commit guard).

Workflow добавления новой runtime fn (например f64.@cbrt):

  1. Добавить RuntimeFn { ... } в src/codegen/runtime_registry.rs.
  2. Реализовать в nova_rt/<module>.c (или wrapper к libc).
  3. Регенерация: nova regen-runtime (или nova-codegen emit-runtime-stubs --root .).
  4. Коммит всех трёх (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-файл.
--modedevdev или release.
--toolchainautoauto, clang, msvc, gcc.
--vcvars PATHauto через vswhereПуть к vcvars64.bat (Windows).
--clang PATHauto detectПуть к clang.exe.
--cg-include PATH<cwd>/compiler-codegenПуть к compiler-codegen/ для include nova_rt/.
--rt-dir PATH<cwd>/compiler-codegen/nova_rtRuntime sources.
--tmp-dir PATH$TEMP/nova_tests или $TMPDIR/nova_testsTmp директория для .c/.exe/.obj.
--display NAMEbasenameOverride display-name в выводе.
--keep-artifactsoffНе удалять артефакты.
--timeout SECS60Per-test timeout.
--gcboehmboehm или 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 PATHnova_testsКорень тестового корпуса.
--stdlib-dir PATHstdКорень std/ (если --include-stdlib).
--include-stdliboffВключить std/* файлы.
--filter SUBSTRFilter по display-name.
--modedevСм. test-build.
--toolchainauto
--vcvars, --clangauto
--cg-include, --rt-dirвычисляются из CWD
--tmp-dir$TEMP/nova_tests или эквивалент
--keep-artifactsoff
--timeout60Per-test timeout.
--jobs N0 (= num_cpus)Параллельные worker'ы.
--formattexttext, json, tap.
-v, --verboseoffOutput PASS-тестов.
-q, --quietoffТолько FAIL + summary.
--results-file PATHФайл last-results.json.
--rerun-failedoffПерезапустить только failed/timeout из results file.
--retries N0Retry на transient AV/race fail'ах (CI default 2).
--gcboehmСм. 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=1Verbose debug-print mono-instances.
NOVA_SMT_BACKEND=trivial|z3Override SMT-backend для контрактов.
NOVA_CACHE_DIR=PATHOverride директории SMT proof cache (default <cwd>/target/).
NOVA_CLANG=PATHOverride clang.exe для test-build/test-all.
NOVA_GCC=PATHOverride пути к gcc.
NOVA_VCVARS=PATHOverride vcvars64.bat (Windows MSVC).
NOVA_MARCH_NATIVE=1Включить -march=native (release builds; non-portable binary).
NOVA_GC_LIB_DIR=PATHOverride директории libgc.a / gc.lib (Boehm).
NOVA_GC_INCLUDE_DIR=PATHOverride include path для gc.h.
VCPKG_ROOT=PATHКорень vcpkg (для авто-резолва libuv / libz3).
CC=nameFallback C compiler (POSIX).
NOVA_VERSION=N.M.KТекущая версия для deprecation diagnostics (Plan 45).
NOVA_FEATURES=f1,f2Cfg feature-set (Plan 42.12).
NOVA_TARGET_OS=nameOverride 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:

МодульЧто
argbindNamed/positional arg binding (Plan 46 / D102).
astТипы AST: Module, Item, Expr, Stmt, Pattern, …
callnormCall-site normalization для named params.
codegenC-бэкенд: CEmitter::emit_module, runtime_registry::all, …
desugarDesugar map-литералов, for-in, и прочих сахаров.
diagСтруктурированные диагностики (Diagnostic, Span, byte_to_line_col).
docPlan 45 — DocModel, рендеры, MCP-server.
importsPlan 35 R31 — cross-file resolver (resolve_imports_inline).
interpTreewalk-интерпретатор (Interpreter::new / load_module / run_main / run_tests).
lexerТокенизация: lex(&src) -> Vec<Token>.
lintsD-rule based lints (lint_module).
manifestnova.toml + D78 path/module enforcement.
parserRecursive-descent parser (parse(&src) -> Result<Module, Diagnostic>).
perf_timerNOVA_PERF_TIMER instrumentation.
test_runnerTest discovery + parallel execution + toolchain detect.
typesType-checker + effect inference (check_module, infer_effects, annotate_map_literals).
verifySMT 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_pathsVec<PathBuf>, alphabetical sort для deterministic build.
  • *_test.nv peers фильтруются если !include_test_peers.
  • X.nv + X/ с direct .nv → ambiguous error.
  • internal/<…> path-protection — import только из parent's descendants.
  • _module.nv convention для 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.cHandler-стек (D61), nova_interrupt / nova_interrupt_ptr.
fibers.cShim над minicoro.h + structured concurrency (Plan 44.5).

Header-only:

HeaderЧто
array.hNovaArray_<T>, NovaOpt_<T> auto-gen helpers.
cast.hD54 narrow casts (saturation, wrap-around semantics).
effects.hNovaThrowKind, nova_throw_cancel, Handler[E, IRT] API.
fibers.hnova_spawn, nova_supervised, nova_cancel_*, M:N runtime.
channels.hChannel[T] mpsc (Plan 44.1), select waiter.
sync.hC11 atomics + mutex для channel hardening.
minicoro.hVendored 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).