1use super::syntax::*;
2use crate::span::Spanned;
3
4impl TranslationUnit {
5 pub fn new() -> Self {
7 Self::default()
8 }
9
10 pub fn remove_voids(&mut self) {
12 self.global_declarations
13 .retain_mut(|decl| match decl.node() {
14 GlobalDeclaration::Void => false,
15 _ => {
16 decl.remove_voids();
17 true
18 }
19 })
20 }
21}
22
23#[cfg(feature = "imports")]
24impl ModulePath {
25 pub fn new(origin: PathOrigin, components: Vec<String>) -> Self {
29 Self { origin, components }
30 }
31
32 pub fn new_root() -> Self {
38 Self::new(PathOrigin::Absolute, vec![])
39 }
40
41 pub fn from_path(path: impl AsRef<std::path::Path>) -> Self {
54 use std::path::Component;
55 let path = path.as_ref().with_extension("");
56 let mut parts = path.components().peekable();
57
58 let origin = match parts.next() {
59 Some(Component::Prefix(_)) => panic!("path starts with a Windows prefix"),
60 Some(Component::RootDir) => PathOrigin::Absolute,
61 Some(Component::CurDir) => PathOrigin::Relative(0),
62 Some(Component::ParentDir) => {
63 let mut n = 1;
64 while let Some(&Component::ParentDir) = parts.peek() {
65 n += 1;
66 parts.next().unwrap();
67 }
68 PathOrigin::Relative(n)
69 }
70 Some(Component::Normal(name)) => {
71 PathOrigin::Package(name.to_string_lossy().to_string())
72 }
73 None => panic!("path is empty"),
74 };
75
76 let components = parts
77 .map(|part| match part {
78 Component::Normal(name) => name.to_string_lossy().to_string(),
79 _ => panic!("unexpected path component"),
80 })
81 .collect::<Vec<_>>();
82
83 Self { origin, components }
84 }
85
86 pub fn to_path_buf(&self) -> std::path::PathBuf {
92 use std::path::PathBuf;
93 let mut fs_path = match &self.origin {
94 PathOrigin::Absolute => PathBuf::from("/"),
95 PathOrigin::Relative(0) => PathBuf::from("."),
96 PathOrigin::Relative(n) => PathBuf::from_iter((0..*n).map(|_| "..")),
97 PathOrigin::Package(name) => PathBuf::from(name),
98 };
99 fs_path.extend(&self.components);
100 fs_path
101 }
102
103 pub fn push(&mut self, item: &str) {
107 self.components.push(item.to_string());
108 }
109
110 pub fn first(&self) -> Option<&str> {
112 self.components.first().map(String::as_str)
113 }
114
115 pub fn last(&self) -> Option<&str> {
117 self.components.last().map(String::as_str)
118 }
119
120 pub fn join(mut self, suffix: impl IntoIterator<Item = String>) -> Self {
122 self.components.extend(suffix);
123 self
124 }
125
126 pub fn join_path(&self, suffix: &Self) -> Self {
137 match suffix.origin {
138 PathOrigin::Absolute => {
139 match self.origin {
140 PathOrigin::Absolute | PathOrigin::Relative(_) => suffix.clone(),
141 PathOrigin::Package(_) => {
142 let origin = self.origin.clone();
144 let components = suffix.components.clone();
145 Self { origin, components }
146 }
147 }
148 }
149 PathOrigin::Relative(n) => {
150 let to_keep = self.components.len().saturating_sub(n);
151 let components = self
152 .components
153 .iter()
154 .take(to_keep)
155 .chain(&suffix.components)
156 .cloned()
157 .collect::<Vec<_>>();
158 let origin = match self.origin {
159 PathOrigin::Absolute | PathOrigin::Package(_) => self.origin.clone(),
160 PathOrigin::Relative(m) => {
161 PathOrigin::Relative(m + n.saturating_sub(self.components.len()))
162 }
163 };
164 Self { origin, components }
165 }
166 PathOrigin::Package(ref suffix_pkg) => {
167 match &self.origin {
168 PathOrigin::Absolute | PathOrigin::Relative(_) => suffix.clone(),
169 PathOrigin::Package(self_pkg) => {
170 let origin = PathOrigin::Package(format!("{self_pkg}/{suffix_pkg}"));
173 let components = suffix.components.clone();
174 Self { origin, components }
175 }
176 }
177 }
178 }
179 }
180
181 pub fn starts_with(&self, prefix: &Self) -> bool {
183 self.origin == prefix.origin
184 && self.components.len() >= prefix.components.len()
185 && prefix
186 .components
187 .iter()
188 .zip(&self.components)
189 .all(|(a, b)| a == b)
190 }
191
192 pub fn is_root(&self) -> bool {
196 self.origin.is_absolute() && self.components.is_empty()
197 }
198}
199
200#[cfg(feature = "imports")]
201#[test]
202fn test_module_path_join() {
203 use std::str::FromStr;
204 let cases = [
206 ("package::m1", "package::foo", "package::foo"),
207 ("package::m1", "self::foo", "package::m1::foo"),
208 ("package::m1", "super::foo", "package::foo"),
209 ("pkg::m1::m2", "package::foo", "pkg::foo"),
210 ("pkg::m1::m2", "self::foo", "pkg::m1::m2::foo"),
211 ("pkg::m1::m2", "super::foo", "pkg::m1::foo"),
212 ("pkg::m1", "super::super::foo", "pkg::foo"),
213 ("super", "super::foo", "super::super::foo"),
214 ("super::m1::m2::m3", "super::super::m4", "super::m1::m4"),
215 ("super", "self::foo", "super::foo"),
216 ("self", "super::foo", "super::foo"),
217 ];
218
219 for (parent, child, expect) in cases {
220 let parent = ModulePath::from_str(parent).unwrap();
221 let child = ModulePath::from_str(child).unwrap();
222 let expect = ModulePath::from_str(expect).unwrap();
223 println!("testing join_paths({parent}, {child}) -> {expect}");
224 assert_eq!(parent.join_path(&child), expect);
225 }
226}
227
228#[cfg(feature = "imports")]
229#[derive(Clone, Copy, PartialEq, Eq, Debug, thiserror::Error)]
230pub enum ModulePathParseError {
231 #[error("module name cannot be empty")]
232 Empty,
233 #[error("`package` must be a prefix of the module path")]
234 MisplacedPackage,
235 #[error("`self` must be a prefix of the module path")]
236 MisplacedSelf,
237 #[error("`super` must be a prefix of the module path")]
238 MisplacedSuper,
239}
240
241#[cfg(feature = "imports")]
242impl std::str::FromStr for ModulePath {
243 type Err = ModulePathParseError;
244
245 fn from_str(s: &str) -> Result<Self, Self::Err> {
250 let mut parts = s.split("::").peekable();
251
252 let origin = match parts.next() {
253 Some("package") => PathOrigin::Absolute,
254 Some("self") => PathOrigin::Relative(0),
255 Some("super") => {
256 let mut n = 1;
257 while let Some(&"super") = parts.peek() {
258 n += 1;
259 parts.next().unwrap();
260 }
261 PathOrigin::Relative(n)
262 }
263 Some("") | None => return Err(ModulePathParseError::Empty),
264 Some(name) => PathOrigin::Package(name.to_string()),
265 };
266
267 let components = parts
268 .map(|part| match part {
269 "package" => Err(ModulePathParseError::MisplacedPackage),
270 "self" => Err(ModulePathParseError::MisplacedSelf),
271 "super" => Err(ModulePathParseError::MisplacedSuper),
272 _ => Ok(part.to_string()),
273 })
274 .collect::<Result<Vec<_>, _>>()?;
275
276 Ok(Self { origin, components })
277 }
278}
279
280#[cfg(feature = "imports")]
281#[test]
282fn test_module_path_fromstr() {
283 use std::str::FromStr;
284
285 let ok_cases = [
286 ("self", ModulePath::new(PathOrigin::Relative(0), vec![])),
287 ("super", ModulePath::new(PathOrigin::Relative(1), vec![])),
288 ("package", ModulePath::new(PathOrigin::Absolute, vec![])),
289 (
290 "a",
291 ModulePath::new(PathOrigin::Package("a".to_string()), vec![]),
292 ),
293 (
294 "super::super::a",
295 ModulePath::new(PathOrigin::Relative(2), vec!["a".to_string()]),
296 ),
297 ];
298 let err_cases = [
299 ("", ModulePathParseError::Empty),
300 ("a::super", ModulePathParseError::MisplacedSuper),
301 ("super::self", ModulePathParseError::MisplacedSelf),
302 ("self::package", ModulePathParseError::MisplacedPackage),
303 ];
304
305 for (s, m) in ok_cases {
306 assert_eq!(ModulePath::from_str(s), Ok(m))
307 }
308 for (s, e) in err_cases {
309 assert_eq!(ModulePath::from_str(s), Err(e))
310 }
311}
312
313impl GlobalDeclaration {
314 pub fn remove_voids(&mut self) {
316 if let GlobalDeclaration::Function(decl) = self {
317 decl.body.remove_voids();
318 }
319 }
320}
321
322impl TypeAlias {
323 pub fn new(ident: Ident, ty: TypeExpression) -> Self {
324 Self {
325 #[cfg(feature = "attributes")]
326 attributes: Default::default(),
327 ident,
328 ty,
329 }
330 }
331}
332
333impl Struct {
334 pub fn new(ident: Ident) -> Self {
335 Self {
336 #[cfg(feature = "attributes")]
337 attributes: Default::default(),
338 ident,
339 members: Default::default(),
340 }
341 }
342}
343
344impl StructMember {
345 pub fn new(ident: Ident, ty: TypeExpression) -> Self {
346 Self {
347 attributes: Default::default(),
348 ident,
349 ty,
350 }
351 }
352}
353
354impl Function {
355 pub fn new(ident: Ident) -> Self {
356 Self {
357 attributes: Default::default(),
358 ident,
359 parameters: Default::default(),
360 return_attributes: Default::default(),
361 return_type: Default::default(),
362 body: Default::default(),
363 }
364 }
365}
366
367impl FormalParameter {
368 pub fn new(ident: Ident, ty: TypeExpression) -> Self {
369 Self {
370 attributes: Default::default(),
371 ident,
372 ty,
373 }
374 }
375}
376
377impl ConstAssert {
378 pub fn new(expression: Expression) -> Self {
379 Self {
380 #[cfg(feature = "attributes")]
381 attributes: Default::default(),
382 expression: expression.into(),
383 }
384 }
385}
386
387impl TypeExpression {
388 pub fn new(ident: Ident) -> Self {
390 Self {
391 #[cfg(feature = "imports")]
392 path: None,
393 ident,
394 template_args: None,
395 }
396 }
397}
398
399impl CompoundStatement {
400 pub fn remove_voids(&mut self) {
402 self.statements.retain_mut(|stmt| match stmt.node_mut() {
403 Statement::Void => false,
404 _ => {
405 stmt.remove_voids();
406 true
407 }
408 })
409 }
410}
411
412impl Statement {
413 pub fn remove_voids(&mut self) {
415 match self {
416 Statement::Compound(stmt) => {
417 stmt.remove_voids();
418 }
419 Statement::If(stmt) => {
420 stmt.if_clause.body.remove_voids();
421 for clause in &mut stmt.else_if_clauses {
422 clause.body.remove_voids();
423 }
424 if let Some(clause) = &mut stmt.else_clause {
425 clause.body.remove_voids();
426 }
427 }
428 Statement::Switch(stmt) => stmt
429 .clauses
430 .iter_mut()
431 .for_each(|clause| clause.body.remove_voids()),
432 Statement::Loop(stmt) => stmt.body.remove_voids(),
433 Statement::For(stmt) => stmt.body.remove_voids(),
434 Statement::While(stmt) => stmt.body.remove_voids(),
435 _ => (),
436 }
437 }
438}
439
440impl From<Ident> for TypeExpression {
441 fn from(ident: Ident) -> Self {
442 Self::new(ident)
443 }
444}
445
446impl From<ExpressionNode> for ReturnStatement {
447 fn from(expression: ExpressionNode) -> Self {
448 Self {
449 #[cfg(feature = "attributes")]
450 attributes: Default::default(),
451 expression: Some(expression),
452 }
453 }
454}
455impl From<Expression> for ReturnStatement {
456 fn from(expression: Expression) -> Self {
457 Self::from(ExpressionNode::from(expression))
458 }
459}
460
461impl From<FunctionCall> for FunctionCallStatement {
462 fn from(call: FunctionCall) -> Self {
463 Self {
464 #[cfg(feature = "attributes")]
465 attributes: Default::default(),
466 call,
467 }
468 }
469}
470
471macro_rules! impl_transitive_from {
475 ($from:ident => $middle:ident => $into:ident) => {
476 impl From<$from> for $into {
477 fn from(value: $from) -> Self {
478 $into::from($middle::from(value))
479 }
480 }
481 };
482}
483
484impl_transitive_from!(bool => LiteralExpression => Expression);
485impl_transitive_from!(i64 => LiteralExpression => Expression);
486impl_transitive_from!(f64 => LiteralExpression => Expression);
487impl_transitive_from!(i32 => LiteralExpression => Expression);
488impl_transitive_from!(u32 => LiteralExpression => Expression);
489impl_transitive_from!(f32 => LiteralExpression => Expression);
490impl_transitive_from!(Ident => TypeExpression => Expression);
491
492pub trait SyntaxNode {
497 fn span(&self) -> Option<Span> {
499 None
500 }
501
502 fn ident(&self) -> Option<Ident> {
504 None
505 }
506
507 fn attributes(&self) -> &[AttributeNode] {
509 &[]
510 }
511 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
513 &mut []
514 }
515 fn contains_attribute(&self, attribute: &Attribute) -> bool {
517 self.attributes().iter().any(|v| v.node() == attribute)
518 }
519 fn retain_attributes_mut<F>(&mut self, _predicate: F)
521 where
522 F: FnMut(&mut Attribute) -> bool,
523 {
524 }
525}
526
527impl<T: SyntaxNode> SyntaxNode for Spanned<T> {
528 fn span(&self) -> Option<Span> {
529 Some(self.span())
530 }
531
532 fn ident(&self) -> Option<Ident> {
533 self.node().ident()
534 }
535
536 fn attributes(&self) -> &[AttributeNode] {
537 self.node().attributes()
538 }
539
540 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
541 self.node_mut().attributes_mut()
542 }
543
544 fn retain_attributes_mut<F>(&mut self, mut f: F)
545 where
546 F: FnMut(&mut Attribute) -> bool,
547 {
548 self.node_mut().retain_attributes_mut(|v| f(v))
549 }
550}
551
552macro_rules! impl_attrs_struct {
553 () => {
554 fn attributes(&self) -> &[AttributeNode] {
555 &self.attributes
556 }
557 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
558 &mut self.attributes
559 }
560 fn retain_attributes_mut<F>(&mut self, mut f: F)
561 where
562 F: FnMut(&mut Attribute) -> bool,
563 {
564 self.attributes.retain_mut(|v| f(v))
565 }
566 };
567}
568
569macro_rules! impl_attrs_enum {
570 ($($variant: path),* $(,)?) => {
571 fn attributes(&self) -> &[AttributeNode] {
572 match self {
573 $(
574 $variant(x) => &x.attributes,
575 )*
576 #[allow(unreachable_patterns)]
577 _ => &[]
578 }
579 }
580 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
581 match self {
582 $(
583 $variant(x) => &mut x.attributes,
584 )*
585 #[allow(unreachable_patterns)]
586 _ => &mut []
587 }
588 }
589 fn retain_attributes_mut<F>(&mut self, mut f: F)
590 where
591 F: FnMut(&mut Attribute) -> bool,
592 {
593 match self {
594 $(
595 $variant(x) => x.attributes.retain_mut(|v| f(v)),
596 )*
597 #[allow(unreachable_patterns)]
598 _ => {}
599 }
600 }
601 };
602}
603
604#[cfg(feature = "imports")]
605impl SyntaxNode for ImportStatement {
606 #[cfg(feature = "attributes")]
607 impl_attrs_struct! {}
608}
609
610impl SyntaxNode for GlobalDirective {
611 #[cfg(feature = "attributes")]
612 impl_attrs_enum! {
613 GlobalDirective::Diagnostic,
614 GlobalDirective::Enable,
615 GlobalDirective::Requires
616 }
617}
618
619impl SyntaxNode for DiagnosticDirective {
620 #[cfg(feature = "attributes")]
621 impl_attrs_struct! {}
622}
623
624impl SyntaxNode for EnableDirective {
625 #[cfg(feature = "attributes")]
626 impl_attrs_struct! {}
627}
628
629impl SyntaxNode for RequiresDirective {
630 #[cfg(feature = "attributes")]
631 impl_attrs_struct! {}
632}
633
634impl SyntaxNode for GlobalDeclaration {
635 fn ident(&self) -> Option<Ident> {
636 match self {
637 GlobalDeclaration::Void => None,
638 GlobalDeclaration::Declaration(decl) => Some(decl.ident.clone()),
639 GlobalDeclaration::TypeAlias(decl) => Some(decl.ident.clone()),
640 GlobalDeclaration::Struct(decl) => Some(decl.ident.clone()),
641 GlobalDeclaration::Function(decl) => Some(decl.ident.clone()),
642 GlobalDeclaration::ConstAssert(_) => None,
643 }
644 }
645
646 #[cfg(feature = "attributes")]
647 impl_attrs_enum! {
648 GlobalDeclaration::Declaration,
649 GlobalDeclaration::TypeAlias,
650 GlobalDeclaration::Struct,
651 GlobalDeclaration::Function,
652 GlobalDeclaration::ConstAssert,
653 }
654}
655
656impl SyntaxNode for Declaration {
657 fn ident(&self) -> Option<Ident> {
658 Some(self.ident.clone())
659 }
660
661 impl_attrs_struct! {}
662}
663
664impl SyntaxNode for TypeAlias {
665 fn ident(&self) -> Option<Ident> {
666 Some(self.ident.clone())
667 }
668
669 #[cfg(feature = "attributes")]
670 impl_attrs_struct! {}
671}
672
673impl SyntaxNode for Struct {
674 fn ident(&self) -> Option<Ident> {
675 Some(self.ident.clone())
676 }
677
678 #[cfg(feature = "attributes")]
679 impl_attrs_struct! {}
680}
681
682impl SyntaxNode for StructMember {
683 fn ident(&self) -> Option<Ident> {
684 Some(self.ident.clone())
685 }
686
687 impl_attrs_struct! {}
688}
689
690impl SyntaxNode for Function {
691 fn ident(&self) -> Option<Ident> {
692 Some(self.ident.clone())
693 }
694
695 impl_attrs_struct! {}
696}
697
698impl SyntaxNode for FormalParameter {
699 fn ident(&self) -> Option<Ident> {
700 Some(self.ident.clone())
701 }
702
703 impl_attrs_struct! {}
704}
705
706impl SyntaxNode for ConstAssert {
707 #[cfg(feature = "attributes")]
708 impl_attrs_struct! {}
709}
710
711impl SyntaxNode for Expression {}
712impl SyntaxNode for LiteralExpression {}
713impl SyntaxNode for ParenthesizedExpression {}
714impl SyntaxNode for NamedComponentExpression {}
715impl SyntaxNode for IndexingExpression {}
716impl SyntaxNode for UnaryExpression {}
717impl SyntaxNode for BinaryExpression {}
718impl SyntaxNode for FunctionCall {}
719impl SyntaxNode for TypeExpression {}
720
721impl SyntaxNode for Statement {
722 #[cfg(feature = "attributes")]
723 impl_attrs_enum! {
724 Statement::Compound,
725 Statement::Assignment,
726 Statement::Increment,
727 Statement::Decrement,
728 Statement::If,
729 Statement::Switch,
730 Statement::Loop,
731 Statement::For,
732 Statement::While,
733 Statement::Break,
734 Statement::Continue,
735 Statement::Return,
736 Statement::Discard,
737 Statement::FunctionCall,
738 Statement::ConstAssert,
739 Statement::Declaration,
740 }
741}
742
743impl SyntaxNode for CompoundStatement {
744 impl_attrs_struct! {}
745}
746
747impl SyntaxNode for AssignmentStatement {
748 #[cfg(feature = "attributes")]
749 impl_attrs_struct! {}
750}
751
752impl SyntaxNode for IncrementStatement {
753 #[cfg(feature = "attributes")]
754 impl_attrs_struct! {}
755}
756
757impl SyntaxNode for DecrementStatement {
758 #[cfg(feature = "attributes")]
759 impl_attrs_struct! {}
760}
761
762impl SyntaxNode for IfStatement {
763 impl_attrs_struct! {}
764}
765
766impl SyntaxNode for IfClause {}
767
768impl SyntaxNode for ElseIfClause {
769 #[cfg(feature = "attributes")]
770 impl_attrs_struct! {}
771}
772
773impl SyntaxNode for ElseClause {
774 #[cfg(feature = "attributes")]
775 impl_attrs_struct! {}
776}
777
778impl SyntaxNode for SwitchStatement {
779 impl_attrs_struct! {}
780}
781
782impl SyntaxNode for SwitchClause {
783 #[cfg(feature = "attributes")]
784 impl_attrs_struct! {}
785}
786
787impl SyntaxNode for LoopStatement {
788 impl_attrs_struct! {}
789}
790
791impl SyntaxNode for ContinuingStatement {
792 #[cfg(feature = "attributes")]
793 impl_attrs_struct! {}
794}
795
796impl SyntaxNode for BreakIfStatement {
797 #[cfg(feature = "attributes")]
798 impl_attrs_struct! {}
799}
800
801impl SyntaxNode for ForStatement {
802 impl_attrs_struct! {}
803}
804
805impl SyntaxNode for WhileStatement {
806 impl_attrs_struct! {}
807}
808
809impl SyntaxNode for BreakStatement {
810 #[cfg(feature = "attributes")]
811 impl_attrs_struct! {}
812}
813
814impl SyntaxNode for ContinueStatement {
815 #[cfg(feature = "attributes")]
816 impl_attrs_struct! {}
817}
818
819impl SyntaxNode for ReturnStatement {
820 #[cfg(feature = "attributes")]
821 impl_attrs_struct! {}
822}
823
824impl SyntaxNode for DiscardStatement {
825 #[cfg(feature = "attributes")]
826 impl_attrs_struct! {}
827}
828
829impl SyntaxNode for FunctionCallStatement {
830 #[cfg(feature = "attributes")]
831 impl_attrs_struct! {}
832}