1use crate::ast::TypeAnnotation;
10use crate::error::{Result, ShapeError};
11use crate::parser::string_literals::parse_string_literal;
12use pest::iterators::Pair;
13use std::collections::HashMap;
14
15use super::{Rule, pair_location};
16
17pub fn parse_type_annotation(pair: Pair<Rule>) -> Result<TypeAnnotation> {
19 let pair_loc = pair_location(&pair);
20
21 match pair.as_rule() {
22 Rule::type_annotation => {
23 let loc = pair_loc.clone();
24 let mut inner = pair.into_inner();
25 let type_part = inner.next().ok_or_else(|| ShapeError::ParseError {
26 message: "expected type annotation content".to_string(),
27 location: Some(loc.clone()),
28 })?;
29 parse_type_annotation(type_part)
30 }
31 Rule::union_type => {
32 let mut types = Vec::new();
33 for inner in pair.into_inner() {
34 types.push(parse_type_annotation(inner)?);
35 }
36 if types.len() == 1 {
37 Ok(types.remove(0))
38 } else {
39 Ok(TypeAnnotation::Union(types))
40 }
41 }
42 Rule::intersection_type => {
43 let mut types = Vec::new();
44 for inner in pair.into_inner() {
45 types.push(parse_type_annotation(inner)?);
46 }
47 if types.len() == 1 {
48 Ok(types.remove(0))
49 } else {
50 Ok(TypeAnnotation::Intersection(types))
51 }
52 }
53 Rule::optional_type => {
54 let inner = pair
55 .clone()
56 .into_inner()
57 .next()
58 .ok_or_else(|| ShapeError::ParseError {
59 message: "expected type in optional type annotation".to_string(),
60 location: Some(pair_loc),
61 })?;
62 let mut ty = parse_type_annotation(inner)?;
63 if pair.as_str().trim_end().ends_with('?') {
64 ty = TypeAnnotation::Optional(Box::new(ty));
65 }
66 Ok(ty)
67 }
68 Rule::primary_type => {
69 let inner = pair
70 .clone()
71 .into_inner()
72 .next()
73 .ok_or_else(|| ShapeError::ParseError {
74 message: "expected type in primary type annotation".to_string(),
75 location: Some(pair_loc),
76 })?;
77 let mut ty = parse_type_annotation(inner)?;
78 let mut remaining = pair.as_str().trim();
79 while remaining.ends_with("[]") {
80 ty = TypeAnnotation::Array(Box::new(ty));
81 remaining = &remaining[..remaining.len() - 2];
82 }
83 Ok(ty)
84 }
85 Rule::non_array_type => {
86 let mut inner = pair.clone().into_inner();
87 let inner_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
88 message: "expected type in non-array type annotation".to_string(),
89 location: Some(pair_loc),
90 })?;
91 if pair.as_str().trim_start().starts_with("Vec<")
92 && inner_pair.as_rule() == Rule::type_annotation
93 {
94 let inner_ty = parse_type_annotation(inner_pair)?;
95 return Ok(TypeAnnotation::Array(Box::new(inner_ty)));
96 }
97 parse_type_annotation(inner_pair)
98 }
99 Rule::basic_type => parse_basic_type(pair.as_str()),
100 Rule::tuple_type => {
101 let mut members = Vec::new();
102 for inner in pair.into_inner() {
103 if inner.as_rule() == Rule::type_annotation {
104 members.push(parse_type_annotation(inner)?);
105 }
106 }
107 Ok(TypeAnnotation::Tuple(members))
108 }
109 Rule::object_type => parse_object_type(pair),
110 Rule::function_type => parse_function_type(pair),
111 Rule::dyn_type => {
112 let trait_names: Vec<String> = pair
113 .into_inner()
114 .filter(|p| p.as_rule() == Rule::ident)
115 .map(|p| p.as_str().to_string())
116 .collect();
117 Ok(TypeAnnotation::Dyn(trait_names))
118 }
119 Rule::unit_type => Ok(TypeAnnotation::Basic("()".to_string())),
120 Rule::generic_type => parse_generic_type(pair),
121 Rule::type_param => {
122 let param = parse_type_param(pair)?;
123 Ok(param.type_annotation)
124 }
125 Rule::ident => Ok(TypeAnnotation::Reference(pair.as_str().to_string())),
126 _ => Err(ShapeError::ParseError {
127 message: format!("invalid type annotation: {:?}", pair.as_rule()),
128 location: Some(pair_loc),
129 }),
130 }
131}
132
133pub fn parse_basic_type(name: &str) -> Result<TypeAnnotation> {
135 Ok(match name {
136 "void" => TypeAnnotation::Void,
137 "any" => TypeAnnotation::Any,
138 "never" => TypeAnnotation::Never,
139 "undefined" => TypeAnnotation::Undefined,
140 other => TypeAnnotation::Basic(other.to_string()),
141 })
142}
143
144pub fn parse_object_type(pair: Pair<Rule>) -> Result<TypeAnnotation> {
146 let mut fields = Vec::new();
147 for inner in pair.into_inner() {
148 if inner.as_rule() == Rule::object_type_member_list {
149 for member in inner.into_inner() {
150 if member.as_rule() == Rule::object_type_member {
151 fields.push(parse_object_type_member(member)?);
152 }
153 }
154 }
155 }
156 Ok(TypeAnnotation::Object(fields))
157}
158
159pub fn parse_object_type_member(pair: Pair<Rule>) -> Result<crate::ast::ObjectTypeField> {
161 let pair_loc = pair_location(&pair);
162 let mut inner = pair.clone().into_inner();
163 let mut annotations = Vec::new();
164
165 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
166 message: "expected field name in object type member".to_string(),
167 location: Some(pair_loc.clone()),
168 })?;
169
170 let name_pair = if first.as_rule() == Rule::annotations {
171 annotations = super::functions::parse_annotations(first)?;
172 inner.next().ok_or_else(|| ShapeError::ParseError {
173 message: "expected field name after annotations in object type member".to_string(),
174 location: Some(pair_loc.clone()),
175 })?
176 } else {
177 first
178 };
179 let name = name_pair.as_str().to_string();
180
181 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
182 message: format!("expected type annotation for field '{}'", name),
183 location: Some(pair_loc),
184 })?;
185 let type_annotation = parse_type_annotation(type_pair)?;
186
187 let before_colon = pair.as_str().split(':').next().unwrap_or("");
188 let optional = before_colon.contains('?');
189
190 Ok(crate::ast::ObjectTypeField {
191 name,
192 optional,
193 type_annotation,
194 annotations,
195 })
196}
197
198pub fn parse_function_type(pair: Pair<Rule>) -> Result<TypeAnnotation> {
200 let mut params = Vec::new();
201 let mut return_type = None;
202
203 for inner in pair.into_inner() {
204 match inner.as_rule() {
205 Rule::type_param_list => {
206 params = parse_type_param_list(inner)?;
207 }
208 Rule::type_annotation => {
209 return_type = Some(parse_type_annotation(inner)?);
210 }
211 _ => {}
212 }
213 }
214
215 let returns = return_type.ok_or_else(|| ShapeError::ParseError {
216 message: "Function type missing return type".to_string(),
217 location: None,
218 })?;
219
220 Ok(TypeAnnotation::Function {
221 params,
222 returns: Box::new(returns),
223 })
224}
225
226pub fn parse_type_param_list(pair: Pair<Rule>) -> Result<Vec<crate::ast::FunctionParam>> {
228 let mut params = Vec::new();
229 for inner in pair.into_inner() {
230 if inner.as_rule() == Rule::type_param {
231 params.push(parse_type_param(inner)?);
232 }
233 }
234 Ok(params)
235}
236
237pub fn parse_type_param(pair: Pair<Rule>) -> Result<crate::ast::FunctionParam> {
239 let pair_loc = pair_location(&pair);
240 let mut inner = pair.clone().into_inner();
241 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
242 message: "expected type parameter content".to_string(),
243 location: Some(pair_loc.clone()),
244 })?;
245
246 if first.as_rule() == Rule::ident {
247 let name = first.as_str().to_string();
248 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
249 message: format!("type parameter '{}' missing type annotation", name),
250 location: Some(pair_loc),
251 })?;
252 let type_annotation = parse_type_annotation(type_pair)?;
253 let before_colon = pair.as_str().split(':').next().unwrap_or("");
254 let optional = before_colon.contains('?');
255 Ok(crate::ast::FunctionParam {
256 name: Some(name),
257 optional,
258 type_annotation,
259 })
260 } else {
261 let type_annotation = parse_type_annotation(first)?;
262 Ok(crate::ast::FunctionParam {
263 name: None,
264 optional: false,
265 type_annotation,
266 })
267 }
268}
269
270pub fn parse_type_params(pair: Pair<Rule>) -> Result<Vec<crate::ast::TypeParam>> {
271 let pair_loc = pair_location(&pair);
272 let mut params = Vec::new();
273 for param_pair in pair.into_inner() {
274 if param_pair.as_rule() == Rule::type_param_name {
275 let mut param_inner = param_pair.into_inner();
276 let name_pair = param_inner.next().ok_or_else(|| ShapeError::ParseError {
277 message: "expected type parameter name".to_string(),
278 location: Some(pair_loc.clone()),
279 })?;
280 let name = name_pair.as_str().to_string();
281 let mut default_type = None;
282 let mut trait_bounds = Vec::new();
283 for remaining in param_inner {
284 match remaining.as_rule() {
285 Rule::type_annotation => {
286 default_type = Some(parse_type_annotation(remaining)?);
287 }
288 Rule::trait_bound_list => {
289 for bound_ident in remaining.into_inner() {
290 if bound_ident.as_rule() == Rule::ident {
291 trait_bounds.push(bound_ident.as_str().to_string());
292 }
293 }
294 }
295 _ => {}
296 }
297 }
298 params.push(crate::ast::TypeParam {
299 name,
300 default_type,
301 trait_bounds,
302 });
303 }
304 }
305 Ok(params)
306}
307
308pub fn parse_builtin_type_decl(pair: Pair<Rule>) -> Result<crate::ast::BuiltinTypeDecl> {
313 let pair_loc = pair_location(&pair);
314 let mut name = String::new();
315 let mut name_span = crate::ast::Span::DUMMY;
316 let mut type_params = None;
317
318 for inner in pair.into_inner() {
319 match inner.as_rule() {
320 Rule::ident => {
321 if name.is_empty() {
322 name = inner.as_str().to_string();
323 name_span = super::pair_span(&inner);
324 }
325 }
326 Rule::type_params => {
327 type_params = Some(parse_type_params(inner)?);
328 }
329 _ => {}
330 }
331 }
332
333 if name.is_empty() {
334 return Err(ShapeError::ParseError {
335 message: "expected builtin type name".to_string(),
336 location: Some(pair_loc),
337 });
338 }
339
340 Ok(crate::ast::BuiltinTypeDecl {
341 name,
342 name_span,
343 type_params,
344 })
345}
346
347pub fn parse_generic_type(pair: Pair<Rule>) -> Result<TypeAnnotation> {
349 let pair_loc = pair_location(&pair);
350 let mut inner = pair.into_inner();
351 let name = inner
352 .next()
353 .ok_or_else(|| ShapeError::ParseError {
354 message: "expected generic type name".to_string(),
355 location: Some(pair_loc.clone()),
356 })?
357 .as_str()
358 .to_string();
359 let mut args = Vec::new();
360 for arg in inner {
361 if arg.as_rule() == Rule::type_annotation {
362 args.push(parse_type_annotation(arg)?);
363 }
364 }
365 if name == "Matrix" {
366 return Err(ShapeError::ParseError {
367 message: "Matrix<T> has been removed; use Mat<T> instead".to_string(),
368 location: Some(pair_loc),
369 });
370 }
371 if (name == "Vec" || name == "Array") && args.len() == 1 {
372 Ok(TypeAnnotation::Array(Box::new(args.remove(0))))
373 } else {
374 Ok(TypeAnnotation::Generic { name, args })
375 }
376}
377
378pub fn parse_comptime_field_overrides(
383 pair: Pair<Rule>,
384) -> Result<HashMap<String, crate::ast::Expr>> {
385 let mut overrides = HashMap::new();
386
387 for override_pair in pair.into_inner() {
388 if override_pair.as_rule() == Rule::comptime_field_override {
389 let mut inner = override_pair.into_inner();
390
391 let key_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
392 message: "Missing parameter name in override".to_string(),
393 location: None,
394 })?;
395 let key = key_pair.as_str().to_string();
396
397 let expr_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
398 message: "Missing expression in parameter override".to_string(),
399 location: None,
400 })?;
401 let expr = super::expressions::parse_expression(expr_pair)?;
402
403 overrides.insert(key, expr);
404 }
405 }
406
407 Ok(overrides)
408}
409
410pub fn parse_struct_type_def(pair: Pair<Rule>) -> Result<crate::ast::StructTypeDef> {
414 let pair_loc = pair_location(&pair);
415 let mut inner = pair.into_inner();
416
417 let mut annotations = Vec::new();
418 let mut type_params = None;
419 let mut fields = Vec::new();
420
421 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
423 message: "Missing struct type name".to_string(),
424 location: Some(pair_loc.clone()),
425 })?;
426
427 let name = if first.as_rule() == Rule::annotations {
428 annotations = super::functions::parse_annotations(first)?;
429 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
430 message: "Missing struct type name after annotations".to_string(),
431 location: Some(pair_loc.clone()),
432 })?;
433 name_pair.as_str().to_string()
434 } else {
435 first.as_str().to_string()
436 };
437
438 for part in inner {
439 match part.as_rule() {
440 Rule::type_params => {
441 type_params = Some(parse_type_params(part)?);
442 }
443 Rule::struct_field_list => {
444 for field_pair in part.into_inner() {
445 if field_pair.as_rule() == Rule::struct_field {
446 fields.push(parse_struct_field(field_pair)?);
447 }
448 }
449 }
450 _ => {}
451 }
452 }
453
454 Ok(crate::ast::StructTypeDef {
455 name,
456 type_params,
457 fields,
458 annotations,
459 native_layout: None,
460 })
461}
462
463pub fn parse_native_struct_type_def(pair: Pair<Rule>) -> Result<crate::ast::StructTypeDef> {
467 let pair_loc = pair_location(&pair);
468 let mut annotations = Vec::new();
469 let mut abi: Option<String> = None;
470 let mut name: Option<String> = None;
471 let mut type_params = None;
472 let mut fields = Vec::new();
473
474 for part in pair.into_inner() {
475 match part.as_rule() {
476 Rule::annotations => {
477 annotations = super::functions::parse_annotations(part)?;
478 }
479 Rule::extern_abi => {
480 abi = Some(super::functions::parse_extern_abi(part)?);
481 }
482 Rule::ident => {
483 if name.is_none() {
484 name = Some(part.as_str().to_string());
485 }
486 }
487 Rule::type_params => {
488 type_params = Some(parse_type_params(part)?);
489 }
490 Rule::struct_field_list => {
491 for field_pair in part.into_inner() {
492 if field_pair.as_rule() == Rule::struct_field {
493 fields.push(parse_struct_field(field_pair)?);
494 }
495 }
496 }
497 _ => {}
498 }
499 }
500
501 let abi = abi.ok_or_else(|| ShapeError::ParseError {
502 message: "native layout type declaration requires an ABI name".to_string(),
503 location: Some(pair_loc.clone()),
504 })?;
505
506 if abi.trim() != "C" {
507 return Err(ShapeError::ParseError {
508 message: format!(
509 "unsupported native ABI '{}': only C is currently supported for type layouts",
510 abi
511 ),
512 location: Some(pair_loc.clone()),
513 });
514 }
515
516 let name = name.ok_or_else(|| ShapeError::ParseError {
517 message: "Missing native layout type name".to_string(),
518 location: Some(pair_loc),
519 })?;
520
521 Ok(crate::ast::StructTypeDef {
522 name,
523 type_params,
524 fields,
525 annotations,
526 native_layout: Some(crate::ast::NativeLayoutBinding { abi }),
527 })
528}
529
530fn parse_struct_field(pair: Pair<Rule>) -> Result<crate::ast::StructField> {
534 let pair_loc = pair_location(&pair);
535 let mut inner = pair.into_inner();
536
537 let mut annotations = vec![];
538 let mut is_comptime = false;
539
540 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
542 message: "Missing struct field name".to_string(),
543 location: Some(pair_loc.clone()),
544 })?;
545
546 let mut current = first;
547
548 if current.as_rule() == Rule::annotations {
549 annotations = super::functions::parse_annotations(current)?;
550 current = inner.next().ok_or_else(|| ShapeError::ParseError {
551 message: "Missing struct field name after annotations".to_string(),
552 location: Some(pair_loc.clone()),
553 })?;
554 }
555
556 if current.as_rule() == Rule::comptime_keyword {
557 is_comptime = true;
558 current = inner.next().ok_or_else(|| ShapeError::ParseError {
559 message: "Missing struct field name after 'comptime'".to_string(),
560 location: Some(pair_loc.clone()),
561 })?;
562 }
563
564 let name = current.as_str().to_string();
565
566 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
567 message: format!("Missing type annotation for struct field '{}'", name),
568 location: Some(pair_loc),
569 })?;
570 let type_annotation = parse_type_annotation(type_pair)?;
571
572 let default_value = if let Some(expr_pair) = inner.next() {
574 Some(super::expressions::parse_expression(expr_pair)?)
575 } else {
576 None
577 };
578
579 Ok(crate::ast::StructField {
580 annotations,
581 is_comptime,
582 name,
583 type_annotation,
584 default_value,
585 })
586}
587
588pub fn parse_type_alias_def(pair: Pair<Rule>) -> Result<crate::ast::TypeAliasDef> {
592 let mut inner = pair.into_inner();
593
594 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
596 message: "Missing type alias name".to_string(),
597 location: None,
598 })?;
599 let name = name_pair.as_str().to_string();
600
601 let mut type_params = None;
603 let mut type_annotation = None;
604 let mut meta_param_overrides = None;
605
606 for part in inner {
607 match part.as_rule() {
608 Rule::type_params => {
609 type_params = Some(parse_type_params(part)?);
611 }
612 Rule::type_annotation => {
613 type_annotation = Some(parse_type_annotation(part)?);
614 }
615 Rule::comptime_field_overrides => {
616 meta_param_overrides = Some(parse_comptime_field_overrides(part)?);
617 }
618 _ => {}
619 }
620 }
621
622 let type_annotation = type_annotation.ok_or_else(|| ShapeError::ParseError {
623 message: "Type alias missing type annotation".to_string(),
624 location: None,
625 })?;
626
627 Ok(crate::ast::TypeAliasDef {
628 name,
629 type_params,
630 type_annotation,
631 meta_param_overrides,
632 })
633}
634
635pub fn parse_enum_def(pair: Pair<Rule>) -> Result<crate::ast::EnumDef> {
639 let pair_loc = pair_location(&pair);
640 let mut inner = pair.into_inner();
641
642 let mut annotations = Vec::new();
643 let mut name = String::new();
644 let mut type_params = None;
645 let mut members = Vec::new();
646
647 for part in inner {
648 match part.as_rule() {
649 Rule::annotations => {
650 annotations = crate::parser::functions::parse_annotations(part)?;
651 }
652 Rule::ident => {
653 if name.is_empty() {
654 name = part.as_str().to_string();
655 }
656 }
657 Rule::type_params => {
658 type_params = Some(parse_type_params(part)?);
659 }
660 Rule::enum_member_list => {
661 for member_pair in part.into_inner() {
662 if member_pair.as_rule() == Rule::enum_member {
663 members.push(parse_enum_member(member_pair)?);
664 }
665 }
666 }
667 Rule::enum_member => {
668 members.push(parse_enum_member(part)?);
669 }
670 _ => {}
671 }
672 }
673
674 if name.is_empty() {
675 return Err(ShapeError::ParseError {
676 message: "Missing enum name".to_string(),
677 location: Some(pair_loc),
678 });
679 }
680
681 Ok(crate::ast::EnumDef {
682 name,
683 type_params,
684 members,
685 annotations,
686 })
687}
688
689fn parse_enum_member(pair: Pair<Rule>) -> Result<crate::ast::EnumMember> {
690 let pair_loc = pair_location(&pair);
691 let inner = pair
692 .into_inner()
693 .next()
694 .ok_or_else(|| ShapeError::ParseError {
695 message: "expected enum member content".to_string(),
696 location: Some(pair_loc.clone()),
697 })?;
698
699 match inner.as_rule() {
700 Rule::enum_variant_unit => {
701 let mut unit_inner = inner.into_inner();
702 let name_pair = unit_inner.next().ok_or_else(|| ShapeError::ParseError {
703 message: "expected enum variant name".to_string(),
704 location: Some(pair_loc.clone()),
705 })?;
706 let name = name_pair.as_str().to_string();
707 let value = if let Some(val_pair) = unit_inner.next() {
708 match val_pair.as_rule() {
709 Rule::string => Some(crate::ast::EnumValue::String(parse_string_literal(
710 val_pair.as_str(),
711 )?)),
712 Rule::number => {
713 let n: f64 =
714 val_pair
715 .as_str()
716 .parse()
717 .map_err(|e| ShapeError::ParseError {
718 message: format!("Invalid enum value number: {}", e),
719 location: Some(pair_loc.clone()),
720 })?;
721 Some(crate::ast::EnumValue::Number(n))
722 }
723 _ => {
724 return Err(ShapeError::ParseError {
725 message: "invalid enum unit value".to_string(),
726 location: Some(pair_loc),
727 });
728 }
729 }
730 } else {
731 None
732 };
733
734 Ok(crate::ast::EnumMember {
735 name,
736 kind: crate::ast::EnumMemberKind::Unit { value },
737 })
738 }
739 Rule::enum_variant_tuple => {
740 let mut tuple_inner = inner.into_inner();
741 let name_pair = tuple_inner.next().ok_or_else(|| ShapeError::ParseError {
742 message: "expected enum variant name".to_string(),
743 location: Some(pair_loc.clone()),
744 })?;
745 let name = name_pair.as_str().to_string();
746 let mut fields = Vec::new();
747 for type_pair in tuple_inner {
748 if type_pair.as_rule() == Rule::type_annotation {
749 fields.push(parse_type_annotation(type_pair)?);
750 }
751 }
752 Ok(crate::ast::EnumMember {
753 name,
754 kind: crate::ast::EnumMemberKind::Tuple(fields),
755 })
756 }
757 Rule::enum_variant_struct => {
758 let mut struct_inner = inner.into_inner();
759 let name_pair = struct_inner.next().ok_or_else(|| ShapeError::ParseError {
760 message: "expected enum variant name".to_string(),
761 location: Some(pair_loc.clone()),
762 })?;
763 let name = name_pair.as_str().to_string();
764 let mut fields = Vec::new();
765 for part in struct_inner {
766 if part.as_rule() == Rule::object_type_member_list {
767 for field_pair in part.into_inner() {
768 if field_pair.as_rule() == Rule::object_type_member {
769 fields.push(parse_object_type_member(field_pair)?);
770 }
771 }
772 }
773 }
774 Ok(crate::ast::EnumMember {
775 name,
776 kind: crate::ast::EnumMemberKind::Struct(fields),
777 })
778 }
779 _ => Err(ShapeError::ParseError {
780 message: format!("unexpected enum member rule: {:?}", inner.as_rule()),
781 location: Some(pair_loc),
782 }),
783 }
784}
785
786pub fn parse_interface_def(pair: Pair<Rule>) -> Result<crate::ast::InterfaceDef> {
790 let pair_loc = pair_location(&pair);
791 let mut inner = pair.into_inner();
792
793 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
794 message: "Missing interface name".to_string(),
795 location: Some(pair_loc.clone()),
796 })?;
797 let name = name_pair.as_str().to_string();
798
799 let mut type_params = None;
800 let mut members = Vec::new();
801
802 for part in inner {
803 match part.as_rule() {
804 Rule::type_params => {
805 type_params = Some(parse_type_params(part)?);
806 }
807 Rule::interface_body => {
808 members = parse_interface_body(part)?;
809 }
810 _ => {}
811 }
812 }
813
814 Ok(crate::ast::InterfaceDef {
815 name,
816 type_params,
817 members,
818 })
819}
820
821pub fn parse_trait_def(pair: Pair<Rule>) -> Result<crate::ast::TraitDef> {
827 let pair_loc = pair_location(&pair);
828 let inner = pair.into_inner();
829
830 let mut annotations = Vec::new();
831 let mut type_params = None;
832 let mut members = Vec::new();
833 let mut name = String::new();
834
835 for part in inner {
837 match part.as_rule() {
838 Rule::annotations => {
839 annotations = crate::parser::functions::parse_annotations(part)?;
840 }
841 Rule::ident => {
842 if name.is_empty() {
843 name = part.as_str().to_string();
844 }
845 }
846 Rule::type_params => {
847 type_params = Some(parse_type_params(part)?);
848 }
849 Rule::trait_body => {
850 members = parse_trait_body(part)?;
851 }
852 _ => {}
853 }
854 }
855
856 if name.is_empty() {
857 return Err(ShapeError::ParseError {
858 message: "Missing trait name".to_string(),
859 location: Some(pair_loc),
860 });
861 }
862
863 Ok(crate::ast::TraitDef {
864 name,
865 type_params,
866 members,
867 annotations,
868 })
869}
870
871fn parse_trait_body(pair: Pair<Rule>) -> Result<Vec<crate::ast::TraitMember>> {
872 let mut members = Vec::new();
873
874 for trait_member in pair.into_inner() {
875 if trait_member.as_rule() != Rule::trait_member {
876 continue;
877 }
878
879 for inner in trait_member.into_inner() {
882 match inner.as_rule() {
883 Rule::associated_type_decl => {
884 let (name, bounds) = parse_associated_type_decl(inner)?;
885 members.push(crate::ast::TraitMember::AssociatedType { name, bounds });
886 }
887 Rule::method_def => {
888 let method = parse_method_def_shared(inner)?;
889 members.push(crate::ast::TraitMember::Default(method));
890 }
891 Rule::interface_member => {
892 let im = parse_interface_member(inner)?;
893 members.push(crate::ast::TraitMember::Required(im));
894 }
895 _ => {} }
897 }
898 }
899
900 Ok(members)
901}
902
903fn parse_associated_type_decl(pair: Pair<Rule>) -> Result<(String, Vec<TypeAnnotation>)> {
905 let mut inner = pair.into_inner();
906
907 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
908 message: "expected associated type name".to_string(),
909 location: None,
910 })?;
911 let name = name_pair.as_str().to_string();
912
913 let mut bounds = Vec::new();
914 for remaining in inner {
915 if remaining.as_rule() == Rule::trait_bound_list {
916 for bound_ident in remaining.into_inner() {
917 if bound_ident.as_rule() == Rule::ident {
918 bounds.push(TypeAnnotation::Basic(bound_ident.as_str().to_string()));
919 }
920 }
921 }
922 }
923
924 Ok((name, bounds))
925}
926
927pub(crate) fn parse_method_def_shared(pair: Pair<Rule>) -> Result<crate::ast::types::MethodDef> {
929 use crate::ast::types::MethodDef;
930
931 let is_async = pair.as_str().trim_start().starts_with("async");
933
934 let mut md_inner = pair.into_inner();
935
936 let name_pair = md_inner.next().ok_or_else(|| ShapeError::ParseError {
937 message: "Missing method name".to_string(),
938 location: None,
939 })?;
940 let name = name_pair.as_str().to_string();
941
942 let mut params = Vec::new();
943 let mut when_clause = None;
944 let mut return_type = None;
945 let mut body = Vec::new();
946
947 for part in md_inner {
948 match part.as_rule() {
949 Rule::function_params => {
950 for param_pair in part.into_inner() {
951 if param_pair.as_rule() == Rule::function_param {
952 params.push(super::functions::parse_function_param(param_pair)?);
953 }
954 }
955 }
956 Rule::when_clause => {
957 if let Some(expr_pair) = part.into_inner().next() {
958 when_clause = Some(Box::new(crate::parser::expressions::parse_expression(
959 expr_pair,
960 )?));
961 }
962 }
963 Rule::return_type => {
964 if let Some(type_pair) = part.into_inner().next() {
965 return_type = Some(parse_type_annotation(type_pair)?);
966 }
967 }
968 Rule::function_body => {
969 body = super::statements::parse_statements(part.into_inner())?;
970 }
971 _ => {}
972 }
973 }
974
975 Ok(MethodDef {
976 name,
977 params,
978 when_clause,
979 return_type,
980 body,
981 is_async,
982 })
983}
984
985fn parse_interface_body(pair: Pair<Rule>) -> Result<Vec<crate::ast::InterfaceMember>> {
986 let mut members = Vec::new();
987 for inner in pair.into_inner() {
988 if inner.as_rule() == Rule::interface_member_list {
989 for member in inner.into_inner() {
990 if member.as_rule() == Rule::interface_member {
991 members.push(parse_interface_member(member)?);
992 }
993 }
994 }
995 }
996 Ok(members)
997}
998
999fn parse_interface_member(pair: Pair<Rule>) -> Result<crate::ast::InterfaceMember> {
1000 let pair_loc = pair_location(&pair);
1001 let raw = pair.as_str();
1002 let trimmed = raw.trim_start();
1003
1004 if trimmed.starts_with('[') {
1005 return parse_interface_index_signature(pair, trimmed);
1006 }
1007
1008 let mut inner = pair.into_inner();
1009 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
1010 message: "expected interface member name".to_string(),
1011 location: Some(pair_loc.clone()),
1012 })?;
1013 let name = name_pair.as_str().to_string();
1014
1015 let (optional, is_method) = parse_interface_member_kind(trimmed, &name);
1016
1017 let mut params = Vec::new();
1018 let mut type_annotation = None;
1019 for part in inner {
1020 match part.as_rule() {
1021 Rule::type_param_list => {
1022 params = parse_type_param_list(part)?;
1023 }
1024 Rule::type_annotation => {
1025 type_annotation = Some(parse_type_annotation(part)?);
1026 }
1027 _ => {}
1028 }
1029 }
1030
1031 let type_annotation = type_annotation.ok_or_else(|| ShapeError::ParseError {
1032 message: format!("interface member '{}' missing type annotation", name),
1033 location: Some(pair_loc),
1034 })?;
1035
1036 if is_method {
1037 Ok(crate::ast::InterfaceMember::Method {
1038 name,
1039 optional,
1040 params,
1041 return_type: type_annotation,
1042 is_async: false,
1043 })
1044 } else {
1045 Ok(crate::ast::InterfaceMember::Property {
1046 name,
1047 optional,
1048 type_annotation,
1049 })
1050 }
1051}
1052
1053fn parse_interface_member_kind(raw: &str, name: &str) -> (bool, bool) {
1054 let trimmed = raw.trim_start();
1055 let Some(mut rest) = trimmed.strip_prefix(name) else {
1056 return (false, false);
1057 };
1058 rest = rest.trim_start();
1059 let mut optional = false;
1060 if rest.starts_with('?') {
1061 optional = true;
1062 rest = rest[1..].trim_start();
1063 }
1064 let is_method = rest.starts_with('(');
1065 (optional, is_method)
1066}
1067
1068fn parse_interface_index_signature(
1069 pair: Pair<Rule>,
1070 raw: &str,
1071) -> Result<crate::ast::InterfaceMember> {
1072 let pair_loc = pair_location(&pair);
1073 let mut inner = pair.into_inner();
1074 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
1075 message: "expected index signature parameter name".to_string(),
1076 location: Some(pair_loc.clone()),
1077 })?;
1078 let param_name = name_pair.as_str().to_string();
1079
1080 let mut return_type = None;
1081 for part in inner {
1082 if part.as_rule() == Rule::type_annotation {
1083 return_type = Some(parse_type_annotation(part)?);
1084 }
1085 }
1086
1087 let return_type = return_type.ok_or_else(|| ShapeError::ParseError {
1088 message: "index signature missing return type".to_string(),
1089 location: Some(pair_loc.clone()),
1090 })?;
1091
1092 let param_type =
1093 parse_index_signature_param_type(raw).ok_or_else(|| ShapeError::ParseError {
1094 message: "index signature missing parameter type".to_string(),
1095 location: Some(pair_loc),
1096 })?;
1097
1098 Ok(crate::ast::InterfaceMember::IndexSignature {
1099 param_name,
1100 param_type,
1101 return_type,
1102 })
1103}
1104
1105fn parse_index_signature_param_type(raw: &str) -> Option<String> {
1106 let trimmed = raw.trim();
1107 let open = trimmed.find('[')?;
1108 let close = trimmed[open + 1..].find(']')? + open + 1;
1109 let inside = trimmed[open + 1..close].trim();
1110 let mut parts = inside.splitn(2, ':');
1111 parts.next()?;
1112 let param_type = parts.next()?.trim();
1113 if param_type == "string" || param_type == "number" {
1114 Some(param_type.to_string())
1115 } else {
1116 None
1117 }
1118}