mon_core/ast.rs
1//! # Abstract Syntax Tree (AST) for MON
2//!
3//! This module defines the data structures that represent the Abstract Syntax Tree (AST) of a
4//! parsed MON document. The AST is a tree-like representation of the source code's structure,
5//! and it is the central data structure used throughout the compilation pipeline.
6//!
7//! ## Architectural Overview
8//!
9//! The AST is generated by the [`Parser`](crate::parser::Parser) from a stream of tokens.
10//! The initial AST is a "raw" representation that has not been semantically analyzed.
11//! This raw tree is then passed to the [`Resolver`](crate::resolver::Resolver), which processes it
12//! by resolving imports, expanding aliases and spreads, and performing type validation.
13//! The final, resolved AST is the main output of the `mon-core` library.
14//!
15//! The nodes of the tree are designed to be easily traversable and to store all necessary
16//! information from the source, including positional data (spans) for accurate error reporting.
17//!
18//! ## Key Data Structures
19//!
20//! - [`MonDocument`]: The root of the AST, containing the root value (typically an object) and a list
21//! of all top-level `import` statements.
22//!
23//! - [`MonValue`]: A wrapper around a [`MonValueKind`] that also includes metadata like a potential
24//! anchor name and its source code position. This is the primary representation of any value in MON.
25//!
26//! - [`MonValueKind`]: An enum that defines the actual type of a value, such as `Object`, `Array`,
27//! `String`, `Number`, `Alias`, etc.
28//!
29//! - [`Member`]: Represents the different kinds of entries within an object, including a `Pair` (key-value),
30//! a `Spread` (`...*my_anchor`), or a `TypeDefinition`.
31//!
32//! - [`TypeDefinition`], [`StructDef`], [`EnumDef`]: These structs represent the schema definition
33//! constructs (`#struct` and `#enum`) in MON.
34//!
35//! - [`SymbolTable`]: A container generated by the resolver to store all resolved type definitions
36//! for easy lookup during validation.
37//!
38//! Developers typically do not need to construct these AST nodes manually. Instead, they are
39//! generated by the `Parser` and consumed by other parts of the library or by language tools.
40use log::error;
41use miette::SourceSpan;
42use std::fmt::{Debug, Display};
43use std::panic::Location;
44
45/// Represents a fully parsed MON document, including the root value and any import statements.
46#[derive(Debug, PartialEq, Clone)]
47pub struct MonDocument {
48 pub root: MonValue,
49 pub imports: Vec<ImportStatement>,
50}
51
52/// Represents a value in a MON document, such as a `string`, `number`, `object`, or `array`...
53/// It also includes metadata like its source position and any associated anchor.
54#[derive(Debug, PartialEq, Clone)]
55pub struct MonValue {
56 pub kind: MonValueKind,
57 pub anchor: Option<String>,
58 pub pos_start: usize,
59 pub pos_end: usize,
60}
61
62impl MonValue {
63 /// Returns the source span of the value, which can be used for error reporting.
64 #[must_use]
65 pub fn get_source_span(&self) -> SourceSpan {
66 SourceSpan::new(self.pos_start.into(), self.pos_end - self.pos_start)
67 }
68}
69
70/// An enum representing the different kinds of values that can exist in a MON document.
71#[derive(Debug, PartialEq, Clone)]
72pub enum MonValueKind {
73 /// A string literal.
74 String(String),
75 /// A floating-point number.
76 Number(f64),
77 /// A boolean value.
78 Boolean(bool),
79 /// A null value.
80 Null,
81 /// An object, containing a vector of `Member`s.
82 Object(Vec<Member>),
83 /// An array, containing a vector of `MonValue`s.
84 Array(Vec<MonValue>),
85 /// An alias to an anchored value.
86 Alias(String),
87 /// An enum variant.
88 EnumValue {
89 enum_name: String,
90 variant_name: String,
91 },
92 /// A spread of an array.
93 ArraySpread(String),
94}
95
96/// Represents a member of a MON object.
97#[derive(Debug, PartialEq, Clone)]
98pub enum Member {
99 /// A key-value pair.
100 Pair(Pair),
101 /// A spread of another object's members.
102 Spread(String),
103 /// An import statement.
104 Import(ImportStatement),
105 /// A type definition (`#struct` or `#enum`).
106 TypeDefinition(TypeDefinition),
107}
108
109/// Represents a key-value pair within a MON object.
110#[derive(Debug, PartialEq, Clone)]
111pub struct Pair {
112 /// The key of the pair.
113 pub key: String,
114 /// The value of the pair.
115 pub value: MonValue,
116 /// An optional type specification used for validation, e.g., `key::String`.
117 ///
118 /// [NOTE] This is lazily generated, check if it exists first
119 pub validation: Option<TypeSpec>,
120}
121
122/// Represents an `import` statement, e.g., `import "path/to/file.mon" as my_namespace;`
123#[derive(Debug, PartialEq, Clone)]
124pub struct ImportStatement {
125 /// The file path to the imported file.
126 pub path: String,
127 /// The specification of what to import (either a namespace or a list of named items).
128 pub spec: ImportSpec,
129 /// The starting character position of this statement in the source text.
130 pub pos_start: usize,
131 /// The ending character position of this statement in the source text.
132 pub pos_end: usize,
133}
134
135/// Defines what is being imported from a file.
136#[derive(Debug, PartialEq, Clone)]
137pub enum ImportSpec {
138 /// Imports the entire file into a single namespace, e.g., `as my_namespace`.
139 Namespace(String),
140 /// Imports specific items (anchors or types) from the file, e.g., `{ MyType, &my_anchor }`.
141 Named(Vec<ImportSpecifier>),
142}
143
144/// Represents a single item being imported by name.
145#[derive(Debug, PartialEq, Clone)]
146pub struct ImportSpecifier {
147 /// The name of the type or anchor to import.
148 pub name: String,
149 /// Whether the imported item is an anchor (e.g., `&my_anchor`).
150 pub is_anchor: bool,
151}
152
153/// Represents a type definition, either a `#struct` or an `#enum`.
154#[derive(Debug, PartialEq, Clone)]
155pub struct TypeDefinition {
156 /// The name of the type being defined.
157 pub name: String,
158 /// The source span of the type's name.
159 pub name_span: SourceSpan,
160 /// The actual definition of the type.
161 pub def_type: TypeDef,
162 /// The starting character position of this definition in the source text.
163 pub pos_start: usize,
164 /// The ending character position of this definition in the source text.
165 pub pos_end: usize,
166}
167
168/// An enum that holds either a struct or an enum definition.
169#[derive(Debug, PartialEq, Clone)]
170pub enum TypeDef {
171 /// A struct definition.
172 Struct(StructDef),
173 /// An enum definition.
174 Enum(EnumDef),
175}
176
177impl TypeDef {
178 /// Returns the source span of the entire type definition.
179 #[must_use]
180 pub fn get_span(&self) -> SourceSpan {
181 match self {
182 TypeDef::Struct(s) => (s.pos_start, s.pos_end - s.pos_start).into(),
183 TypeDef::Enum(e) => (e.pos_start, e.pos_end - e.pos_start).into(),
184 }
185 }
186}
187
188/// Represents a `#struct` definition.
189#[derive(Debug, PartialEq, Clone)]
190pub struct StructDef {
191 /// The fields that make up the struct.
192 pub fields: Vec<FieldDef>,
193 /// The starting character position of this struct definition in the source text.
194 pub pos_start: usize,
195 /// The ending character position of this struct definition in the source text.
196 pub pos_end: usize,
197}
198
199/// Represents a single field within a `#struct` definition.
200#[derive(Debug, PartialEq, Clone)]
201pub struct FieldDef {
202 /// The name of the field.
203 pub name: String,
204 /// The type specification for this field.
205 pub type_spec: TypeSpec,
206 /// An optional default value for this field.
207 pub default_value: Option<MonValue>,
208}
209
210/// Represents an `#enum` definition.
211#[derive(Debug, PartialEq, Clone)]
212pub struct EnumDef {
213 /// The variants of the enum.
214 pub variants: Vec<String>,
215 /// The starting character position of this enum definition in the source text.
216 pub pos_start: usize,
217 /// The ending character position of this enum definition in the source text.
218 pub pos_end: usize,
219}
220
221/// Represents a type specification used for validation, e.g., `:: String` or `:: [Number, String]`.
222#[derive(Debug, PartialEq, Clone)]
223pub enum TypeSpec {
224 /// A simple type, e.g., `String`, `MyStruct`.
225 Simple(String, SourceSpan),
226 /// A collection type, e.g., `[Number, String]`.
227 Collection(Vec<TypeSpec>, SourceSpan),
228 /// A spread type within a collection, e.g., `[Number...]`.
229 Spread(Box<TypeSpec>, SourceSpan),
230}
231
232impl TypeSpec {
233 #[must_use]
234 pub fn get_span(&self) -> SourceSpan {
235 match self {
236 TypeSpec::Simple(_, span)
237 | TypeSpec::Collection(_, span)
238 | TypeSpec::Spread(_, span) => *span,
239 }
240 }
241}
242
243impl Display for Member {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 match self {
246 Member::Pair(p) => write!(f, "Pair({}: {})", p.key, p.value),
247 Member::Spread(s) => write!(f, "Spread(...*{s})"),
248 Member::Import(i) => write!(f, "Import({i:?})"),
249 Member::TypeDefinition(t) => write!(f, "TypeDef({t:?})"),
250 }
251 }
252}
253
254/// A table to store resolved symbols, such as type definitions, from a MON document and its imports.
255#[derive(Debug, Default)]
256pub struct SymbolTable {
257 /// A map of type names to their definitions.
258 pub types: std::collections::HashMap<String, TypeDefinition>,
259}
260
261impl SymbolTable {
262 /// Creates a new, empty symbol table.
263 #[must_use]
264 pub fn new() -> Self {
265 Self::default()
266 }
267}
268
269impl Display for MonDocument {
270 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
271 write!(f, "{}", self.root)
272 }
273}
274
275impl Display for MonValueKind {
276 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
277 match self {
278 MonValueKind::String(s) => write!(f, "\"{s}\""),
279 MonValueKind::Number(n) => write!(f, "{n}"),
280 MonValueKind::Boolean(b) => write!(f, "{b}"),
281 MonValueKind::Null => write!(f, "null"),
282 MonValueKind::Object(o) => {
283 write!(f, "{{ ")?;
284 for (i, member) in o.iter().enumerate() {
285 write!(f, "{member}")?;
286 if i < o.len() - 1 {
287 write!(f, ", ")?;
288 }
289 }
290 write!(f, " }}")
291 }
292 MonValueKind::Array(a) => {
293 write!(f, "[ ")?;
294 for (i, value) in a.iter().enumerate() {
295 write!(f, "{value}")?;
296 if i < a.len() - 1 {
297 write!(f, ", ")?;
298 }
299 }
300 write!(f, "]")
301 }
302 MonValueKind::Alias(a) => write!(f, "*{a}"),
303 MonValueKind::EnumValue {
304 enum_name,
305 variant_name,
306 } => {
307 write!(f, "${enum_name}.{variant_name}")
308 }
309 MonValueKind::ArraySpread(s) => write!(f, "...*{s}"),
310 }
311 }
312}
313
314impl Display for MonValue {
315 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
316 if let Some(anchor) = &self.anchor {
317 write!(f, "&{anchor} ")?;
318 }
319 write!(f, "{}", self.kind)
320 }
321}
322
323impl Pair {
324 #[track_caller]
325 #[must_use]
326 pub fn get_span(&self) -> SourceSpan {
327 match &self.validation {
328 None => {
329 error!(
330 "No validation for `Pair`found for source span called by {}",
331 Location::caller()
332 );
333 SourceSpan::new(0.into(), 0)
334 }
335 Some(valid) => match valid {
336 TypeSpec::Simple(_, source_span)
337 | TypeSpec::Collection(_, source_span)
338 | TypeSpec::Spread(_, source_span) => *source_span,
339 },
340 }
341 }
342}