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}