mago_codex/ttype/resolution.rs
1use serde::Deserialize;
2use serde::Serialize;
3
4use crate::misc::GenericParent;
5use crate::ttype::union::TUnion;
6
7/// Holds contextual information necessary for resolving generic template types (`@template`).
8///
9/// This context typically includes the definitions of template parameters available in the current scope
10/// (e.g., from class or function `@template` tags) and any concrete types that these templates
11/// have been resolved to (e.g., when a generic class is instantiated or a generic method is called).
12#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub struct TypeResolutionContext {
14 /// Definitions of template types available in this context, including their constraints.
15 template_definitions: Vec<(String, Vec<(GenericParent, TUnion)>)>,
16
17 /// Concrete types that template parameters (often from an outer scope) resolve to
18 /// within this specific context.
19 resolved_template_types: Vec<(String, TUnion)>,
20}
21
22/// Provides a default, empty type resolution context.
23impl Default for TypeResolutionContext {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl TypeResolutionContext {
30 /// Creates a new, empty `TypeResolutionContext` with no defined or resolved template types.
31 pub fn new() -> Self {
32 Self { template_definitions: vec![], resolved_template_types: vec![] }
33 }
34
35 /// Checks if this context is empty, meaning it has no template definitions or resolved types.
36 #[inline]
37 pub fn is_empty(&self) -> bool {
38 self.template_definitions.is_empty() && self.resolved_template_types.is_empty()
39 }
40
41 /// Adds a template type definition (e.g., from an `@template T of Constraint` tag).
42 ///
43 /// # Arguments
44 ///
45 /// * `name`: The name of the template parameter (e.g., `"T"`).
46 /// * `constraints`: A list of constraints, each specifying the origin (parent) and the constraint type.
47 pub fn with_template_definition(mut self, name: String, constraints: Vec<(GenericParent, TUnion)>) -> Self {
48 self.template_definitions.push((name, constraints));
49 self
50 }
51
52 /// Adds a mapping indicating that a template parameter resolves to a specific concrete type
53 /// within this context.
54 ///
55 /// # Arguments
56 ///
57 /// * `name`: The name of the template parameter (e.g., `"T"`).
58 /// * `resolved_type`: The concrete `TUnion` type that `name` resolves to here.
59 pub fn with_resolved_template_type(mut self, name: String, resolved_type: TUnion) -> Self {
60 self.resolved_template_types.push((name, resolved_type));
61 self
62 }
63
64 /// Returns a slice of the defined template parameters and their constraints for this context.
65 #[inline]
66 pub fn get_template_definitions(&self) -> &[(String, Vec<(GenericParent, TUnion)>)] {
67 &self.template_definitions
68 }
69
70 /// Returns a mutable slice of the defined template parameters and their constraints for this context.
71 #[inline]
72 pub fn get_template_definitions_mut(&mut self) -> &mut [(String, Vec<(GenericParent, TUnion)>)] {
73 &mut self.template_definitions
74 }
75
76 /// Returns a slice of the template parameters that have resolved to concrete types in this context.
77 #[inline]
78 pub fn get_resolved_template_types(&self) -> &[(String, TUnion)] {
79 &self.resolved_template_types
80 }
81
82 /// Returns a mutable slice of the template parameters that have resolved to concrete types in this context.
83 #[inline]
84 pub fn get_resolved_template_types_mut(&mut self) -> &mut [(String, TUnion)] {
85 &mut self.resolved_template_types
86 }
87
88 /// Looks up the constraints for a specific template parameter defined in this context.
89 ///
90 /// # Arguments
91 ///
92 /// * `name`: The name of the template parameter (e.g., `"T"`) to look up.
93 ///
94 /// # Returns
95 ///
96 /// `Some` containing a reference to the vector of constraints if the template is defined, `None` otherwise.
97 pub fn get_template_definition(&self, name: &str) -> Option<&Vec<(GenericParent, TUnion)>> {
98 self.template_definitions.iter().find(|(n, _)| n == name).map(|(_, constraints)| constraints)
99 }
100
101 /// Checks if a specific template parameter is defined in this context.
102 ///
103 /// # Arguments
104 ///
105 /// * `name`: The name of the template parameter (e.g., `"T"`) to check.
106 ///
107 /// # Returns
108 ///
109 /// `true` if the template parameter is defined, `false` otherwise.
110 pub fn has_template_definition(&self, name: &str) -> bool {
111 self.template_definitions.iter().any(|(n, _)| n == name)
112 }
113
114 /// Looks up the concrete type that a specific template parameter resolves to in this context.
115 ///
116 /// # Arguments
117 ///
118 /// * `name`: The name of the template parameter (e.g., `"T"`) to look up.
119 ///
120 /// # Returns
121 ///
122 /// `Some` containing a reference to the resolved `TUnion` type if found, `None` otherwise.
123 /// Note: If multiple entries exist for the same name (due to shadowing or errors),
124 /// this currently returns the first match found.
125 pub fn get_resolved_template_type(&self, name: &str) -> Option<&TUnion> {
126 self.resolved_template_types
127 .iter()
128 // Iterate in reverse if shadowing means the *last* added binding is correct
129 // .rev()
130 .find(|(n, _)| n == name)
131 .map(|(_, resolved_type)| resolved_type)
132 }
133
134 /// Checks if this context contains any template definitions or resolved template types.
135 #[inline]
136 pub fn has_templates(&self) -> bool {
137 !self.template_definitions.is_empty() || !self.resolved_template_types.is_empty()
138 }
139
140 /// Checks if a specific template parameter has a concrete resolved type in this context.
141 #[inline]
142 pub fn is_template_resolved(&self, name: &str) -> bool {
143 self.resolved_template_types.iter().any(|(n, _)| n == name)
144 }
145
146 /// Merges another `TypeResolutionContext` into this one, combining their template definitions
147 /// and resolved types.
148 #[inline]
149 pub fn merge(&mut self, other: TypeResolutionContext) {
150 self.template_definitions.extend(other.template_definitions);
151 self.resolved_template_types.extend(other.resolved_template_types);
152 }
153}