shape_runtime/context/
registries.rs1use super::super::annotation_context::AnnotationContext;
7use super::super::type_methods::TypeMethodRegistry;
8use super::super::type_schema::TypeSchemaRegistry;
9use shape_ast::ast::{AnnotationDef, AnnotationHandlerType, FunctionDef};
10use shape_ast::error::{Result, ShapeError};
11use std::sync::Arc;
12
13impl super::ExecutionContext {
14 pub fn register_annotation(&mut self, def: AnnotationDef) {
19 self.annotation_registry.register(def);
20 }
21
22 pub fn annotation_context(&self) -> &AnnotationContext {
24 &self.annotation_context
25 }
26
27 pub fn annotation_context_mut(&mut self) -> &mut AnnotationContext {
29 &mut self.annotation_context
30 }
31
32 pub fn register_function(&mut self, function: FunctionDef) {
36 self.dispatch_on_define_hooks(&function);
37 }
38
39 fn dispatch_on_define_hooks(&mut self, func: &FunctionDef) {
45 for annotation in &func.annotations {
46 if let Some(ann_def) = self.annotation_registry.get(&annotation.name).cloned() {
48 for handler in &ann_def.handlers {
50 if handler.handler_type == AnnotationHandlerType::OnDefine {
51 self.execute_on_define_handler(&ann_def, handler, func);
53 }
54 }
55 }
56 }
59 }
60
61 fn execute_on_define_handler(
67 &mut self,
68 _ann_def: &AnnotationDef,
69 _handler: &shape_ast::ast::AnnotationHandler,
70 _func: &FunctionDef,
71 ) {
72 self.sync_pattern_registry_from_annotation_context();
73 }
74
75 fn sync_pattern_registry_from_annotation_context(&mut self) {}
81
82 pub fn lookup_pattern(&self, name: &str) -> Result<&super::super::closure::Closure> {
86 self.pattern_registry
87 .get(name)
88 .ok_or_else(|| ShapeError::RuntimeError {
89 message: format!(
90 "Unknown pattern: '{}'. Did you register it in the pattern registry?",
91 name
92 ),
93 location: None,
94 })
95 }
96
97 pub fn type_method_registry(&self) -> &Arc<TypeMethodRegistry> {
99 &self.type_method_registry
100 }
101
102 pub fn type_schema_registry(&self) -> &Arc<TypeSchemaRegistry> {
104 &self.type_schema_registry
105 }
106
107 pub fn register_enum(&mut self, enum_def: shape_ast::ast::EnumDef) {
116 self.enum_registry.register(enum_def);
117 }
118
119 pub fn lookup_enum(&self, name: &str) -> Option<&shape_ast::ast::EnumDef> {
121 self.enum_registry.get(name)
122 }
123
124 pub fn has_enum(&self, name: &str) -> bool {
126 self.enum_registry.contains(name)
127 }
128
129 pub fn enum_registry(&self) -> &super::EnumRegistry {
131 &self.enum_registry
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::super::ExecutionContext;
138 use shape_ast::ast::{
139 Annotation, AnnotationDef, AnnotationHandler, AnnotationHandlerType, Expr, FunctionDef,
140 Span,
141 };
142
143 #[test]
144 fn test_register_annotation_definition() {
145 let mut ctx = ExecutionContext::new_empty();
146
147 let ann_def = AnnotationDef {
149 name: "test_annotation".to_string(),
150 name_span: Span::DUMMY,
151 params: vec![],
152 allowed_targets: None,
153 handlers: vec![],
154 span: Span::DUMMY,
155 };
156
157 ctx.register_annotation(ann_def);
158
159 assert!(ctx.annotation_registry.contains("test_annotation"));
161 }
162
163 #[test]
164 fn test_function_without_annotations_registers_normally() {
165 let mut ctx = ExecutionContext::new_empty();
166
167 let func = FunctionDef {
168 name: "my_func".to_string(),
169 name_span: Span::DUMMY,
170 type_params: None,
171 params: vec![],
172 return_type: None,
173 body: vec![],
174 annotations: vec![],
175 where_clause: None,
176 is_async: false,
177 is_comptime: false,
178 };
179
180 ctx.register_function(func);
181
182 }
186
187 #[test]
188 fn test_function_with_undefined_annotation_no_crash() {
189 let mut ctx = ExecutionContext::new_empty();
190
191 let func = FunctionDef {
193 name: "annotated_func".to_string(),
194 name_span: Span::DUMMY,
195 type_params: None,
196 params: vec![],
197 return_type: None,
198 body: vec![],
199 annotations: vec![Annotation {
200 name: "undefined".to_string(),
201 args: vec![],
202 span: Span::DUMMY,
203 }],
204 where_clause: None,
205 is_async: false,
206 is_comptime: false,
207 };
208
209 ctx.register_function(func);
211
212 }
216
217 #[test]
218 fn test_annotation_with_on_define_handler_is_called() {
219 let mut ctx = ExecutionContext::new_empty();
220
221 let ann_def = AnnotationDef {
225 name: "tracked".to_string(),
226 name_span: Span::DUMMY,
227 params: vec![],
228 allowed_targets: None,
229 handlers: vec![AnnotationHandler {
230 handler_type: AnnotationHandlerType::OnDefine,
231 params: vec![shape_ast::ast::AnnotationHandlerParam {
232 name: "fn".to_string(),
233 is_variadic: false,
234 }],
235 return_type: None,
236 body: Expr::Identifier("fn".to_string(), Span::DUMMY),
239 span: Span::DUMMY,
240 }],
241 span: Span::DUMMY,
242 };
243
244 ctx.register_annotation(ann_def);
245
246 let func = FunctionDef {
248 name: "tracked_func".to_string(),
249 name_span: Span::DUMMY,
250 type_params: None,
251 params: vec![],
252 return_type: None,
253 body: vec![],
254 annotations: vec![Annotation {
255 name: "tracked".to_string(),
256 args: vec![],
257 span: Span::DUMMY,
258 }],
259 where_clause: None,
260 is_async: false,
261 is_comptime: false,
262 };
263
264 ctx.register_function(func);
266
267 }
271
272 #[test]
273 fn test_lookup_pattern_not_found() {
274 let ctx = ExecutionContext::new_empty();
275
276 let result = ctx.lookup_pattern("nonexistent");
277 assert!(result.is_err());
278
279 let err = result.unwrap_err();
280 let msg = format!("{}", err);
281 assert!(msg.contains("Unknown pattern"));
282 assert!(msg.contains("nonexistent"));
283 }
284
285 #[test]
286 fn test_annotation_context_registry_access() {
287 let mut ctx = ExecutionContext::new_empty();
288
289 {
291 let registry = ctx.annotation_context_mut().registry("test_registry");
292 registry.set(
293 "key1".to_string(),
294 shape_value::ValueWord::from_string(std::sync::Arc::new("value1".to_string())),
295 );
296 }
297
298 let registry = ctx.annotation_context_mut().registry("test_registry");
300 assert!(registry.get("key1").is_some());
301 }
302}