1use 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 doc_comment: None,
152 params: vec![],
153 allowed_targets: None,
154 handlers: vec![],
155 span: Span::DUMMY,
156 };
157
158 ctx.register_annotation(ann_def);
159
160 assert!(ctx.annotation_registry.contains("test_annotation"));
162 }
163
164 #[test]
165 fn test_function_without_annotations_registers_normally() {
166 let mut ctx = ExecutionContext::new_empty();
167
168 let func = FunctionDef {
169 name: "my_func".to_string(),
170 name_span: Span::DUMMY,
171 doc_comment: None,
172 type_params: None,
173 params: vec![],
174 return_type: None,
175 body: vec![],
176 annotations: vec![],
177 where_clause: None,
178 is_async: false,
179 is_comptime: false,
180 };
181
182 ctx.register_function(func);
183
184 }
188
189 #[test]
190 fn test_function_with_undefined_annotation_no_crash() {
191 let mut ctx = ExecutionContext::new_empty();
192
193 let func = FunctionDef {
195 name: "annotated_func".to_string(),
196 name_span: Span::DUMMY,
197 doc_comment: None,
198 type_params: None,
199 params: vec![],
200 return_type: None,
201 body: vec![],
202 annotations: vec![Annotation {
203 name: "undefined".to_string(),
204 args: vec![],
205 span: Span::DUMMY,
206 }],
207 where_clause: None,
208 is_async: false,
209 is_comptime: false,
210 };
211
212 ctx.register_function(func);
214
215 }
219
220 #[test]
221 fn test_annotation_with_on_define_handler_is_called() {
222 let mut ctx = ExecutionContext::new_empty();
223
224 let ann_def = AnnotationDef {
228 name: "tracked".to_string(),
229 name_span: Span::DUMMY,
230 doc_comment: None,
231 params: vec![],
232 allowed_targets: None,
233 handlers: vec![AnnotationHandler {
234 handler_type: AnnotationHandlerType::OnDefine,
235 params: vec![shape_ast::ast::AnnotationHandlerParam {
236 name: "fn".to_string(),
237 is_variadic: false,
238 }],
239 return_type: None,
240 body: Expr::Identifier("fn".to_string(), Span::DUMMY),
243 span: Span::DUMMY,
244 }],
245 span: Span::DUMMY,
246 };
247
248 ctx.register_annotation(ann_def);
249
250 let func = FunctionDef {
252 name: "tracked_func".to_string(),
253 name_span: Span::DUMMY,
254 doc_comment: None,
255 type_params: None,
256 params: vec![],
257 return_type: None,
258 body: vec![],
259 annotations: vec![Annotation {
260 name: "tracked".to_string(),
261 args: vec![],
262 span: Span::DUMMY,
263 }],
264 where_clause: None,
265 is_async: false,
266 is_comptime: false,
267 };
268
269 ctx.register_function(func);
271
272 }
276
277 #[test]
278 fn test_lookup_pattern_not_found() {
279 let ctx = ExecutionContext::new_empty();
280
281 let result = ctx.lookup_pattern("nonexistent");
282 assert!(result.is_err());
283
284 let err = result.unwrap_err();
285 let msg = format!("{}", err);
286 assert!(msg.contains("Unknown pattern"));
287 assert!(msg.contains("nonexistent"));
288 }
289
290 #[test]
291 fn test_annotation_context_registry_access() {
292 let mut ctx = ExecutionContext::new_empty();
293
294 {
296 let registry = ctx.annotation_context_mut().registry("test_registry");
297 registry.set(
298 "key1".to_string(),
299 shape_value::ValueWord::from_string(std::sync::Arc::new("value1".to_string())),
300 );
301 }
302
303 let registry = ctx.annotation_context_mut().registry("test_registry");
305 assert!(registry.get("key1").is_some());
306 }
307}