1use crate::ast::{
4 AnnotationDef, AnnotationHandler, AnnotationHandlerParam, AnnotationHandlerType,
5 FunctionParameter,
6};
7use crate::error::{Result, ShapeError};
8use crate::parser::Rule;
9use crate::parser::expressions::control_flow::parse_block_expr;
10use crate::parser::pair_span;
11use crate::parser::types::parse_type_annotation;
12use pest::iterators::Pair;
13
14pub fn parse_annotation_def(pair: Pair<Rule>) -> Result<AnnotationDef> {
27 let span = pair_span(&pair);
28 let mut inner = pair.into_inner();
29
30 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
31 message: "Missing annotation name".to_string(),
32 location: None,
33 })?;
34 let name = name_pair.as_str().to_string();
35 let name_span = pair_span(&name_pair);
36
37 let mut params: Vec<FunctionParameter> = Vec::new();
38 let mut handlers = Vec::new();
39 let mut allowed_targets: Option<Vec<crate::ast::AnnotationTargetKind>> = None;
40
41 for part in inner {
42 match part.as_rule() {
43 Rule::annotation_def_params => {
44 for param_pair in part.into_inner() {
45 if param_pair.as_rule() == Rule::ident {
46 let pattern = crate::ast::DestructurePattern::Identifier(
47 param_pair.as_str().to_string(),
48 pair_span(¶m_pair),
49 );
50 params.push(FunctionParameter {
51 pattern,
52 is_const: false,
53 is_reference: false,
54 is_mut_reference: false,
55 is_out: false,
56 type_annotation: None,
57 default_value: None,
58 });
59 }
60 }
61 }
62 Rule::annotation_body => {
63 for body_item in part.into_inner() {
64 let item = if body_item.as_rule() == Rule::annotation_body_item {
65 body_item
66 .into_inner()
67 .next()
68 .ok_or_else(|| ShapeError::ParseError {
69 message: "empty annotation body item".to_string(),
70 location: None,
71 })?
72 } else {
73 body_item
74 };
75
76 match item.as_rule() {
77 Rule::annotation_handler => {
78 handlers.push(parse_annotation_handler(item)?);
79 }
80 Rule::annotation_targets_decl => {
81 let mut targets = Vec::new();
82 for target_pair in item.into_inner() {
83 if target_pair.as_rule() != Rule::annotation_target_kind {
84 continue;
85 }
86 let kind = match target_pair.as_str() {
87 "function" => crate::ast::AnnotationTargetKind::Function,
88 "type" => crate::ast::AnnotationTargetKind::Type,
89 "module" => crate::ast::AnnotationTargetKind::Module,
90 "expression" => crate::ast::AnnotationTargetKind::Expression,
91 "block" => crate::ast::AnnotationTargetKind::Block,
92 "await_expr" => crate::ast::AnnotationTargetKind::AwaitExpr,
93 "binding" => crate::ast::AnnotationTargetKind::Binding,
94 other => {
95 return Err(ShapeError::ParseError {
96 message: format!(
97 "unknown annotation target kind '{}'",
98 other
99 ),
100 location: None,
101 });
102 }
103 };
104 targets.push(kind);
105 }
106 allowed_targets = Some(targets);
107 }
108 _ => {}
109 }
110 }
111 }
112 _ => {}
113 }
114 }
115
116 Ok(AnnotationDef {
117 name,
118 name_span,
119 doc_comment: None,
120 params,
121 allowed_targets,
122 handlers,
123 span,
124 })
125}
126
127fn parse_annotation_handler(pair: Pair<Rule>) -> Result<AnnotationHandler> {
129 let span = pair_span(&pair);
130 let mut inner = pair.into_inner();
131
132 let handler_name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
134 message: "Missing annotation handler name".to_string(),
135 location: None,
136 })?;
137
138 let handler_kind = handler_name_pair
139 .as_str()
140 .split_whitespace()
141 .collect::<Vec<_>>()
142 .join(" ");
143
144 let handler_type = match handler_kind.as_str() {
145 "on_define" => AnnotationHandlerType::OnDefine,
146 "before" => AnnotationHandlerType::Before,
147 "after" => AnnotationHandlerType::After,
148 "metadata" => AnnotationHandlerType::Metadata,
149 "comptime pre" => AnnotationHandlerType::ComptimePre,
150 "comptime post" => AnnotationHandlerType::ComptimePost,
151 other => {
152 return Err(ShapeError::ParseError {
153 message: format!(
154 "unknown annotation handler type '{}'. Expected `on_define`, `before`, `after`, `metadata`, `comptime pre`, or `comptime post`",
155 other
156 ),
157 location: None,
158 });
159 }
160 };
161
162 let mut params = Vec::new();
164 let mut return_type = None;
165 let mut body = None;
166
167 for part in inner {
168 match part.as_rule() {
169 Rule::annotation_handler_params => {
170 for param_pair in part.into_inner() {
171 if param_pair.as_rule() == Rule::annotation_handler_param {
172 let raw = param_pair.as_str().trim();
173 let (name, is_variadic) = if let Some(rest) = raw.strip_prefix("...") {
174 (rest.trim().to_string(), true)
175 } else {
176 (raw.to_string(), false)
177 };
178 if !name.is_empty() {
179 params.push(AnnotationHandlerParam { name, is_variadic });
180 }
181 }
182 }
183 }
184 Rule::return_type => {
185 if let Some(type_pair) = part.into_inner().next() {
187 return_type = Some(parse_type_annotation(type_pair)?);
188 }
189 }
190 Rule::block_expr => {
191 body = Some(parse_block_expr(part)?);
192 }
193 _ => {}
194 }
195 }
196
197 let body = body.ok_or_else(|| ShapeError::ParseError {
198 message: "Missing annotation handler body".to_string(),
199 location: None,
200 })?;
201
202 Ok(AnnotationHandler {
203 handler_type,
204 params,
205 return_type,
206 body,
207 span,
208 })
209}
210
211pub fn parse_extend_statement(pair: Pair<Rule>) -> Result<crate::ast::ExtendStatement> {
212 use crate::ast::types::TypeName;
213
214 let mut inner = pair.into_inner();
215
216 let type_name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
218 message: "Missing type name in extend statement".to_string(),
219 location: None,
220 })?;
221
222 let type_name = {
223 let mut tn_inner = type_name_pair.into_inner();
224 let name_pair = tn_inner.next().ok_or_else(|| ShapeError::ParseError {
225 message: "Missing type name identifier".to_string(),
226 location: None,
227 })?;
228 let name = name_pair.as_str().to_string();
229 let type_args: Vec<_> = tn_inner
230 .map(|p| parse_type_annotation(p))
231 .collect::<Result<Vec<_>>>()?;
232 if type_args.is_empty() {
233 TypeName::Simple(name.into())
234 } else {
235 TypeName::Generic { name: name.into(), type_args }
236 }
237 };
238
239 let mut methods = Vec::new();
241 for method_pair in inner {
242 if matches!(
243 method_pair.as_rule(),
244 Rule::documented_method_def | Rule::method_def
245 ) {
246 methods.push(super::types::parse_documented_method_def_shared(
247 method_pair,
248 )?);
249 }
250 }
251
252 Ok(crate::ast::ExtendStatement { type_name, methods })
253}
254
255pub fn parse_impl_block(pair: Pair<Rule>) -> Result<crate::ast::ImplBlock> {
259 let mut inner = pair.into_inner();
260
261 let trait_name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
263 message: "Missing trait name in impl block".to_string(),
264 location: None,
265 })?;
266 let trait_name = parse_type_name(trait_name_pair)?;
267
268 let target_type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
270 message: "Missing target type in impl block".to_string(),
271 location: None,
272 })?;
273 let target_type = parse_type_name(target_type_pair)?;
274
275 let mut impl_name = None;
277 let mut methods = Vec::new();
278 let mut associated_type_bindings = Vec::new();
279 let mut where_clause = None;
280 for member_pair in inner {
281 if member_pair.as_rule() == Rule::impl_name {
282 let name_pair =
283 member_pair
284 .into_inner()
285 .next()
286 .ok_or_else(|| ShapeError::ParseError {
287 message: "Missing impl name after 'as'".to_string(),
288 location: None,
289 })?;
290 impl_name = Some(name_pair.as_str().to_string());
291 continue;
292 }
293 if member_pair.as_rule() == Rule::where_clause {
294 where_clause = Some(super::functions::parse_where_clause(member_pair)?);
295 continue;
296 }
297 if member_pair.as_rule() != Rule::impl_member {
298 continue;
299 }
300 for child in member_pair.into_inner() {
301 match child.as_rule() {
302 Rule::associated_type_binding => {
303 let binding = parse_associated_type_binding(child)?;
304 associated_type_bindings.push(binding);
305 }
306 Rule::documented_method_def | Rule::method_def => {
307 methods.push(super::types::parse_documented_method_def_shared(child)?);
308 }
309 _ => {}
310 }
311 }
312 }
313
314 Ok(crate::ast::ImplBlock {
315 trait_name,
316 target_type,
317 impl_name,
318 methods,
319 associated_type_bindings,
320 where_clause,
321 })
322}
323
324fn parse_associated_type_binding(
326 pair: Pair<Rule>,
327) -> Result<crate::ast::types::AssociatedTypeBinding> {
328 let mut inner = pair.into_inner();
329
330 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
331 message: "expected associated type name in binding".to_string(),
332 location: None,
333 })?;
334 let name = name_pair.as_str().to_string();
335
336 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
337 message: format!("expected type annotation for associated type '{}'", name),
338 location: None,
339 })?;
340 let concrete_type = super::types::parse_type_annotation(type_pair)?;
341
342 Ok(crate::ast::types::AssociatedTypeBinding {
343 name,
344 concrete_type,
345 })
346}
347
348fn parse_type_name(pair: Pair<Rule>) -> Result<crate::ast::types::TypeName> {
350 use crate::ast::types::TypeName;
351
352 let mut tn_inner = pair.into_inner();
353 let name_pair = tn_inner.next().ok_or_else(|| ShapeError::ParseError {
354 message: "Missing type name identifier".to_string(),
355 location: None,
356 })?;
357 let name = name_pair.as_str().to_string();
358 let type_args: Vec<_> = tn_inner
359 .map(|p| super::types::parse_type_annotation(p))
360 .collect::<Result<Vec<_>>>()?;
361 if type_args.is_empty() {
362 Ok(TypeName::Simple(name.into()))
363 } else {
364 Ok(TypeName::Generic { name: name.into(), type_args })
365 }
366}
367
368pub fn parse_optimize_statement(_pair: Pair<Rule>) -> Result<crate::ast::OptimizeStatement> {
369 Err(ShapeError::ParseError {
370 message: "parse_optimize_statement not yet implemented".to_string(),
371 location: None,
372 })
373}