/
nv-lang
/
nova
Обзор
Документация
Войти
/
nv-lang
/
nova
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
std/src/reflect.nv
162 строки
7 KB
Evgeniy Golovin
docs(endocs): root — translate bench, sort, reflect /// docs to English
01 авг 2026, 02:53
01 авг 2026, 02:53
2d8be0e
Код
Авторство
О чём код?
// std/reflect.nv — Plan 222.8 Ф.1 (D438): формато- и домено-независимая // структурная рефлексия типов. // // `TypeShape` описывает «какая форма у типа» (record/sum/примитив/ // контейнер) БЕЗ единого слова про HTTP/OpenAPI/JSON — пригодно любому // потребителю (OpenAPI-эмиттер, GraphQL SDL, CLI-генератор, дебаг-принтер). // Протокол `Reflect` синтезируется компилятором (compiler-codegen/src/ // protocols/auto_derive.rs, `synthesize_reflect`) для record/sum-типов с // явным `#impl(Reflect)` — тот же field-walk, что у Serialize/Deserialize // (D340/D341/D435), opt-in, ноль цены для кода, которое не просило. // // Wire-имена полей `Record` — ПОСЛЕ rename/rename_all (D435) резолва: то, // что реально уйдёт на wire, а не сырое Nova-имя поля. `Sum.repr` кодирует // разметку (внешняя/внутренняя/смежная/untagged) из уже распарсенных // `#serde(tag/content/untagged)` (D382) — синтез Reflect переиспользует // `serde_tagging_mode` ЦЕЛИКОМ, включая её `untagged`-гейт // (`[M-180-untagged-codegen-mono]`) — документированное упрощение D438, не // скрытая связка (Reflect сам json.nv не трогает). // // Рекурсия: граф типов виден компилятору НА СИНТЕЗЕ — в точке back-edge // цикла (self-referential / mutually recursive типы) эмитится `Ref(name)` // вместо бесконечного инлайна. Значение всегда конечно ПО ПОСТРОЕНИЮ. // // `Opaque(name)` — форма НЕ описывается схемой (сырые типы вроде // ServerRequest, попадающие полями в extractor-бандл, но не для схемы). // Компилятор его НИКОГДА сам не синтезирует — только РУЧНЫЕ реализации // протокола `Reflect` (библиотечные обёртки) решают, что непрозрачно. module std.reflect /// Sum tagging on the wire (D382/D435 `#serde(tag/content/untagged)`). /// `External` — serde default (a type without tagging attributes). export type SumRepr enum | External | Tagged(str) | TaggedContent(str, str) | Untagged /// The structural shape of a type — independent of the format/domain. /// /// - `Record(name, fields)` — a record type; `fields` — `(wire_name, shape)` in /// declaration order, AFTER rename/rename_all; `#serde(skip)` fields /// are excluded (never reach the wire). /// - `Sum(name, repr, variants)` — a sum type; `variants` — `(variant_name, /// shape)`; a unit variant → `Unit`; a single-element tuple variant → /// TRANSPARENTLY the shape of the element itself (no wrapper); a tuple variant with 2+ /// elements → a synthetic `Record(variant_name, [("0", ..), ("1", ..)])` /// (positional fields by index); a record variant → `Record(variant_name, /// [(field, shape), ..])` with RAW field names (rename/rename_all for /// sum variants is out of D435 scope, `[M-126-sum-*-rich]`). /// - `Ref(name)` — back-edge of a recursive type: the type `name` is already unfolding /// higher up the graph (see the module docstring). /// - `Arr(items)` — a homogeneous container (`Vec[T]`/`[]T`). /// - `Opt(inner)` — `Option[T]`. /// - `Opaque(name)` — the shape is intentionally not described (see the module /// docstring); the compiler does not synthesize it. export type TypeShape enum | Record(str, [](str, TypeShape)) | Sum(str, SumRepr, [](str, TypeShape)) | Ref(str) | Str | Int | Float | Bool | Unit | Arr(TypeShape) | Opt(TypeShape) | Opaque(str) /// `.reflect()` — a STATIC method (describes the TYPE, independent of the value). /// The compiler synthesizes the body for record/sum types with an explicit `#impl(Reflect)` /// (auto_derive.rs); the blanket implementations below cover primitives and /// containers. `Opaque` — ONLY through a manual implementation of this protocol. /// /// # Examples /// ```nova /// #impl(Reflect) /// type User { id int, name str } /// /// match User.reflect() { /// Record(name, fields) => assert(name == "User" && fields.len() == 2) /// _ => assert(false) /// } /// ``` #unstable export type Reflect protocol { .reflect() -> TypeShape } // ────────────────────────────────────────────────────────────────────────── // Blanket-реализации: примитивы. // ────────────────────────────────────────────────────────────────────────── #unstable #impl(Reflect) fn int.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn i8.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn i16.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn i32.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn i64.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn uint.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn u8.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn u16.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn u32.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn u64.reflect() -> TypeShape => Int #unstable #impl(Reflect) fn f32.reflect() -> TypeShape => Float #unstable #impl(Reflect) fn f64.reflect() -> TypeShape => Float #unstable #impl(Reflect) fn bool.reflect() -> TypeShape => Bool #unstable #impl(Reflect) fn str.reflect() -> TypeShape => Str // ────────────────────────────────────────────────────────────────────────── // Blanket-реализации: контейнеры. `[]T` — синтаксический алиас `Vec[T]` // (методы применимы к обеим формам записи). // ────────────────────────────────────────────────────────────────────────── /// `Vec[T]`/`[]T` — a homogeneous container. #unstable #impl(Reflect) fn[T Reflect] []T.reflect() -> TypeShape => Arr(T.reflect()) /// `Option[T]`. #unstable #impl(Reflect) fn Option[T Reflect].reflect() -> TypeShape => Opt(T.reflect())