mib_rs/ir/mod.rs
1//! Intermediate representation produced by [lowering](crate::lower) the AST.
2//!
3//! The IR is language-independent: SMIv1 and SMIv2 constructs are unified
4//! (e.g. `TRAP-TYPE` and `NOTIFICATION-TYPE` both become [`Notification`]).
5//! Type and OID references remain unresolved strings until the resolver phase
6//! transforms the IR into a fully resolved [`Mib`](crate::mib::Mib).
7//!
8//! Unlike the AST, the IR generally uses plain `String` values instead of
9//! [`Ident`](crate::ast::Ident) nodes. References that need precise diagnostics
10//! use [`NameRef`], and optional clauses are represented as empty strings rather
11//! than `Option`s.
12
13pub mod definition;
14pub mod oid;
15pub mod syntax;
16
17pub use definition::*;
18pub use oid::{OidAssignment, OidComponent};
19pub use syntax::*;
20
21use crate::source::{SourceId, SourceRange};
22use crate::types::{Diagnostic, Language};
23
24/// A normalized, language-independent MIB module.
25///
26/// Lowering transforms AST structures into this simplified representation
27/// independent of whether the source was SMIv1 or SMIv2.
28#[derive(Debug, Clone)]
29pub struct Module {
30 /// Canonical module name (e.g. `"IF-MIB"`).
31 pub name: String,
32 /// Detected SMI language version, or [`Language::Unknown`] when syntax and
33 /// imports provide insufficient or conflicting version evidence.
34 pub language: Language,
35 /// Flattened imports: one [`Import`] per imported symbol.
36 pub imports: Vec<Import>,
37 /// All definitions in source order.
38 pub definitions: Vec<Definition>,
39 /// Range covering the entire module, or `None` for a generated module.
40 pub range: Option<SourceRange>,
41 /// Diagnostics collected during lowering.
42 pub diagnostics: Vec<Diagnostic>,
43 /// Compilation-local source document containing this module.
44 pub(crate) source_id: Option<SourceId>,
45}
46
47impl Module {
48 /// Creates a new module with the given name and source range. All other fields
49 /// are initialized to empty/default values.
50 pub fn new(name: String, range: Option<SourceRange>) -> Self {
51 let source_id = range.map(SourceRange::source);
52 Module {
53 name,
54 language: Language::Unknown,
55 imports: Vec::new(),
56 definitions: Vec::new(),
57 range,
58 diagnostics: Vec::new(),
59 source_id,
60 }
61 }
62
63 /// Returns an iterator over the names of all definitions.
64 pub fn definition_names(&self) -> impl Iterator<Item = &str> {
65 self.definitions.iter().map(|d| d.name())
66 }
67}
68
69/// A single imported symbol, flattened from the AST's grouped format.
70#[derive(Debug, Clone)]
71pub struct Import {
72 /// Source module name (the FROM target).
73 pub module: String,
74 /// Imported symbol name.
75 pub symbol: String,
76 /// Source range of the symbol in the `IMPORTS` section.
77 pub range: SourceRange,
78}