Skip to main content

vexil_lang/ir/
mod.rs

1//! # Stability: Tier 1
2//!
3//! Intermediate representation for compiled Vexil schemas.
4//!
5//! The IR is produced by the lowering pass and refined by the type checker.
6//! All type references are resolved to [`TypeId`] handles into a [`TypeRegistry`],
7//! and wire sizes are computed for fixed-layout types.
8
9pub mod types;
10
11pub use types::{
12    DeprecatedInfo, Encoding, FieldEncoding, ResolvedAnnotations, ResolvedType, TombstoneDef,
13    TypeId, TypeRegistry, WireSize,
14};
15
16use crate::ast::{DefaultValue, EnumBacking};
17use crate::span::Span;
18use smol_str::SmolStr;
19
20/// A single-file compilation result.
21///
22/// Contains the type registry, the list of types declared in this file,
23/// and the schema-level namespace and annotations. Imported types live in
24/// the registry but are **not** listed in `declarations`.
25#[derive(Debug, Clone)]
26pub struct CompiledSchema {
27    /// Namespace segments, e.g. `["net", "example", "types"]`.
28    pub namespace: Vec<SmolStr>,
29    /// Schema-level annotations (version, doc, etc.).
30    pub annotations: ResolvedAnnotations,
31    /// All type definitions reachable from this schema (declared + imported).
32    pub registry: TypeRegistry,
33    /// Type IDs of declarations **defined** in this file (excludes imports).
34    pub declarations: Vec<TypeId>,
35}
36
37/// A type definition in the Vexil IR.
38///
39/// Each variant corresponds to one of the six declaration forms in the
40/// Vexil language. Marked `#[non_exhaustive]` to allow future expansion.
41#[derive(Debug, Clone)]
42#[non_exhaustive]
43pub enum TypeDef {
44    /// A message with ordered, typed fields.
45    Message(MessageDef),
46    /// A closed or open enumeration.
47    Enum(EnumDef),
48    /// A bitmask / flag set.
49    Flags(FlagsDef),
50    /// A tagged union (sum type).
51    Union(UnionDef),
52    /// A newtype wrapper around another type.
53    Newtype(NewtypeDef),
54    /// A compile-time configuration record (not encoded on the wire).
55    Config(ConfigDef),
56}
57
58/// A message type definition with ordered, typed fields.
59#[derive(Debug, Clone)]
60pub struct MessageDef {
61    pub name: SmolStr,
62    pub span: Span,
63    pub fields: Vec<FieldDef>,
64    pub tombstones: Vec<TombstoneDef>,
65    pub annotations: ResolvedAnnotations,
66    pub wire_size: Option<WireSize>,
67}
68
69/// A single field within a message or union variant.
70#[derive(Debug, Clone)]
71pub struct FieldDef {
72    pub name: SmolStr,
73    pub span: Span,
74    pub ordinal: u32,
75    pub resolved_type: ResolvedType,
76    pub encoding: FieldEncoding,
77    pub annotations: ResolvedAnnotations,
78}
79
80#[derive(Debug, Clone)]
81pub struct EnumDef {
82    pub name: SmolStr,
83    pub span: Span,
84    /// Explicit backing type specified by the user (`: u8`, `: u16`, etc.).
85    /// `None` means no explicit backing — `wire_bits` is auto-computed by typeck.
86    pub backing: Option<EnumBacking>,
87    pub variants: Vec<EnumVariantDef>,
88    pub tombstones: Vec<TombstoneDef>,
89    pub annotations: ResolvedAnnotations,
90    /// Computed by typeck: number of bits used on the wire.
91    /// For explicit backing this equals the backing type width;
92    /// for auto-sized enums this is the minimal bit width for the variant count.
93    pub wire_bits: u8,
94}
95
96/// A single variant within an enum type.
97#[derive(Debug, Clone)]
98pub struct EnumVariantDef {
99    pub name: SmolStr,
100    pub span: Span,
101    pub ordinal: u32,
102    pub annotations: ResolvedAnnotations,
103}
104
105#[derive(Debug, Clone)]
106pub struct FlagsDef {
107    pub name: SmolStr,
108    pub span: Span,
109    pub bits: Vec<FlagsBitDef>,
110    pub tombstones: Vec<TombstoneDef>,
111    pub annotations: ResolvedAnnotations,
112    /// Computed by typeck: number of bytes used on the wire (1, 2, 4, or 8).
113    pub wire_bytes: u8,
114}
115
116/// A single bit definition within a flags type.
117#[derive(Debug, Clone)]
118pub struct FlagsBitDef {
119    pub name: SmolStr,
120    pub span: Span,
121    pub bit: u32,
122    pub annotations: ResolvedAnnotations,
123}
124
125/// A tagged union (sum type) definition.
126#[derive(Debug, Clone)]
127pub struct UnionDef {
128    pub name: SmolStr,
129    pub span: Span,
130    pub variants: Vec<UnionVariantDef>,
131    pub tombstones: Vec<TombstoneDef>,
132    pub annotations: ResolvedAnnotations,
133    pub wire_size: Option<WireSize>,
134}
135
136/// A single variant within a union type.
137#[derive(Debug, Clone)]
138pub struct UnionVariantDef {
139    pub name: SmolStr,
140    pub span: Span,
141    pub ordinal: u32,
142    pub fields: Vec<FieldDef>,
143    pub tombstones: Vec<TombstoneDef>,
144    pub annotations: ResolvedAnnotations,
145}
146
147/// A newtype wrapper around another type.
148#[derive(Debug, Clone)]
149pub struct NewtypeDef {
150    pub name: SmolStr,
151    pub span: Span,
152    pub inner_type: ResolvedType,
153    pub terminal_type: ResolvedType,
154    pub annotations: ResolvedAnnotations,
155}
156
157/// A compile-time configuration record (not wire-encoded).
158#[derive(Debug, Clone)]
159pub struct ConfigDef {
160    pub name: SmolStr,
161    pub span: Span,
162    pub fields: Vec<ConfigFieldDef>,
163    pub annotations: ResolvedAnnotations,
164}
165
166/// A single field within a config record.
167#[derive(Debug, Clone)]
168pub struct ConfigFieldDef {
169    pub name: SmolStr,
170    pub span: Span,
171    pub resolved_type: ResolvedType,
172    pub default_value: DefaultValue,
173    pub annotations: ResolvedAnnotations,
174}