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 if self_pkg.rsplit('/').next() == suffix_pkg.rsplit('/').next() {
171 let origin = self.origin.clone();
173 let components = suffix.components.clone();
174 Self { origin, components }
175 } else {
176 let origin = PathOrigin::Package(format!("{self_pkg}/{suffix_pkg}"));
179 let components = suffix.components.clone();
180 Self { origin, components }
181 }
182 }
183 }
184 }
185 }
186 }
187
188 pub fn starts_with(&self, prefix: &Self) -> bool {
190 self.origin == prefix.origin
191 && self.components.len() >= prefix.components.len()
192 && prefix
193 .components
194 .iter()
195 .zip(&self.components)
196 .all(|(a, b)| a == b)
197 }
198
199 pub fn is_root(&self) -> bool {
203 self.origin.is_absolute() && self.components.is_empty()
204 }
205}
206
207#[cfg(feature = "imports")]
208#[test]
209fn test_module_path_join() {
210 use std::str::FromStr;
211 let cases = [
212 ("package::m1", "package::foo", "package::foo"),
213 ("package::m1", "self::foo", "package::m1::foo"),
214 ("package::m1", "super::foo", "package::foo"),
215 ("pkg::m1::m2", "package::foo", "pkg::foo"),
216 ("pkg::m1::m2", "self::foo", "pkg::m1::m2::foo"),
217 ("pkg::m1::m2", "super::foo", "pkg::m1::foo"),
218 ("pkg::m1", "super::super::foo", "pkg::foo"),
219 ("lygia::m1", "lygia::math", "lygia::math"),
220 ("lygia::m1", "pkg/lygia", "lygia"),
221 ("pkg/lygia::m1", "lygia", "pkg/lygia"),
222 ("pkg/lygia::m1", "lygia::math", "pkg/lygia::math"),
223 ("pkg1/lygia::m1", "pkg2/lygia::math", "pkg1/lygia::math"),
224 ("super", "super::foo", "super::super::foo"),
225 ("super::m1::m2::m3", "super::super::m4", "super::m1::m4"),
226 ("super", "self::foo", "super::foo"),
227 ("self", "super::foo", "super::foo"),
228 ];
229
230 for (parent, child, expect) in cases {
231 let parent = ModulePath::from_str(parent).unwrap();
232 let child = ModulePath::from_str(child).unwrap();
233 let expect = ModulePath::from_str(expect).unwrap();
234 println!("testing ModulePath::join_path({parent}, {child}) -> {expect}");
235 assert_eq!(parent.join_path(&child), expect);
236 }
237}
238
239#[cfg(feature = "imports")]
240#[derive(Clone, Copy, PartialEq, Eq, Debug, thiserror::Error)]
241pub enum ModulePathParseError {
242 #[error("module name cannot be empty")]
243 Empty,
244 #[error("`package` must be a prefix of the module path")]
245 MisplacedPackage,
246 #[error("`self` must be a prefix of the module path")]
247 MisplacedSelf,
248 #[error("`super` must be a prefix of the module path")]
249 MisplacedSuper,
250}
251
252#[cfg(feature = "imports")]
253impl std::str::FromStr for ModulePath {
254 type Err = ModulePathParseError;
255
256 fn from_str(s: &str) -> Result<Self, Self::Err> {
261 let mut parts = s.split("::").peekable();
262
263 let origin = match parts.next() {
264 Some("package") => PathOrigin::Absolute,
265 Some("self") => PathOrigin::Relative(0),
266 Some("super") => {
267 let mut n = 1;
268 while let Some(&"super") = parts.peek() {
269 n += 1;
270 parts.next().unwrap();
271 }
272 PathOrigin::Relative(n)
273 }
274 Some("") | None => return Err(ModulePathParseError::Empty),
275 Some(name) => PathOrigin::Package(name.to_string()),
276 };
277
278 let components = parts
279 .map(|part| match part {
280 "package" => Err(ModulePathParseError::MisplacedPackage),
281 "self" => Err(ModulePathParseError::MisplacedSelf),
282 "super" => Err(ModulePathParseError::MisplacedSuper),
283 _ => Ok(part.to_string()),
284 })
285 .collect::<Result<Vec<_>, _>>()?;
286
287 Ok(Self { origin, components })
288 }
289}
290
291#[cfg(feature = "imports")]
292#[test]
293fn test_module_path_fromstr() {
294 use std::str::FromStr;
295
296 let ok_cases = [
297 ("self", ModulePath::new(PathOrigin::Relative(0), vec![])),
298 ("super", ModulePath::new(PathOrigin::Relative(1), vec![])),
299 ("package", ModulePath::new(PathOrigin::Absolute, vec![])),
300 (
301 "a",
302 ModulePath::new(PathOrigin::Package("a".to_string()), vec![]),
303 ),
304 (
305 "super::super::a",
306 ModulePath::new(PathOrigin::Relative(2), vec!["a".to_string()]),
307 ),
308 ];
309 let err_cases = [
310 ("", ModulePathParseError::Empty),
311 ("a::super", ModulePathParseError::MisplacedSuper),
312 ("super::self", ModulePathParseError::MisplacedSelf),
313 ("self::package", ModulePathParseError::MisplacedPackage),
314 ];
315
316 for (s, m) in ok_cases {
317 assert_eq!(ModulePath::from_str(s), Ok(m))
318 }
319 for (s, e) in err_cases {
320 assert_eq!(ModulePath::from_str(s), Err(e))
321 }
322}
323
324impl GlobalDeclaration {
325 pub fn remove_voids(&mut self) {
327 if let GlobalDeclaration::Function(decl) = self {
328 decl.body.remove_voids();
329 }
330 }
331}
332
333impl TypeAlias {
334 pub fn new(ident: Ident, ty: TypeExpression) -> Self {
335 Self {
336 #[cfg(feature = "attributes")]
337 attributes: Default::default(),
338 ident,
339 ty,
340 }
341 }
342}
343
344impl Struct {
345 pub fn new(ident: Ident) -> Self {
346 Self {
347 #[cfg(feature = "attributes")]
348 attributes: Default::default(),
349 ident,
350 members: Default::default(),
351 }
352 }
353}
354
355impl StructMember {
356 pub fn new(ident: Ident, ty: TypeExpression) -> Self {
357 Self {
358 attributes: Default::default(),
359 ident,
360 ty,
361 }
362 }
363}
364
365impl Function {
366 pub fn new(ident: Ident) -> Self {
367 Self {
368 attributes: Default::default(),
369 ident,
370 parameters: Default::default(),
371 return_attributes: Default::default(),
372 return_type: Default::default(),
373 body: Default::default(),
374 }
375 }
376}
377
378impl FormalParameter {
379 pub fn new(ident: Ident, ty: TypeExpression) -> Self {
380 Self {
381 attributes: Default::default(),
382 ident,
383 ty,
384 }
385 }
386}
387
388impl ConstAssert {
389 pub fn new(expression: Expression) -> Self {
390 Self {
391 #[cfg(feature = "attributes")]
392 attributes: Default::default(),
393 expression: expression.into(),
394 }
395 }
396}
397
398impl TypeExpression {
399 pub fn new(ident: Ident) -> Self {
401 Self {
402 #[cfg(feature = "imports")]
403 path: None,
404 ident,
405 template_args: None,
406 }
407 }
408}
409
410impl CompoundStatement {
411 pub fn remove_voids(&mut self) {
413 self.statements.retain_mut(|stmt| match stmt.node_mut() {
414 Statement::Void => false,
415 _ => {
416 stmt.remove_voids();
417 true
418 }
419 })
420 }
421}
422
423impl Statement {
424 pub fn remove_voids(&mut self) {
426 match self {
427 Statement::Compound(stmt) => {
428 stmt.remove_voids();
429 }
430 Statement::If(stmt) => {
431 stmt.if_clause.body.remove_voids();
432 for clause in &mut stmt.else_if_clauses {
433 clause.body.remove_voids();
434 }
435 if let Some(clause) = &mut stmt.else_clause {
436 clause.body.remove_voids();
437 }
438 }
439 Statement::Switch(stmt) => stmt
440 .clauses
441 .iter_mut()
442 .for_each(|clause| clause.body.remove_voids()),
443 Statement::Loop(stmt) => stmt.body.remove_voids(),
444 Statement::For(stmt) => stmt.body.remove_voids(),
445 Statement::While(stmt) => stmt.body.remove_voids(),
446 _ => (),
447 }
448 }
449}
450
451impl From<Ident> for TypeExpression {
452 fn from(ident: Ident) -> Self {
453 Self::new(ident)
454 }
455}
456
457impl From<ExpressionNode> for ReturnStatement {
458 fn from(expression: ExpressionNode) -> Self {
459 Self {
460 #[cfg(feature = "attributes")]
461 attributes: Default::default(),
462 expression: Some(expression),
463 }
464 }
465}
466impl From<Expression> for ReturnStatement {
467 fn from(expression: Expression) -> Self {
468 Self::from(ExpressionNode::from(expression))
469 }
470}
471
472impl From<FunctionCall> for FunctionCallStatement {
473 fn from(call: FunctionCall) -> Self {
474 Self {
475 #[cfg(feature = "attributes")]
476 attributes: Default::default(),
477 call,
478 }
479 }
480}
481
482macro_rules! impl_transitive_from {
486 ($from:ident => $middle:ident => $into:ident) => {
487 impl From<$from> for $into {
488 fn from(value: $from) -> Self {
489 $into::from($middle::from(value))
490 }
491 }
492 };
493}
494
495impl_transitive_from!(bool => LiteralExpression => Expression);
496impl_transitive_from!(i64 => LiteralExpression => Expression);
497impl_transitive_from!(f64 => LiteralExpression => Expression);
498impl_transitive_from!(i32 => LiteralExpression => Expression);
499impl_transitive_from!(u32 => LiteralExpression => Expression);
500impl_transitive_from!(f32 => LiteralExpression => Expression);
501impl_transitive_from!(Ident => TypeExpression => Expression);
502
503pub trait SyntaxNode {
508 fn span(&self) -> Option<Span> {
510 None
511 }
512
513 fn ident(&self) -> Option<Ident> {
515 None
516 }
517
518 fn attributes(&self) -> &[AttributeNode] {
520 &[]
521 }
522 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
524 &mut []
525 }
526 fn contains_attribute(&self, attribute: &Attribute) -> bool {
528 self.attributes().iter().any(|v| v.node() == attribute)
529 }
530 fn retain_attributes_mut<F>(&mut self, _predicate: F)
532 where
533 F: FnMut(&mut Attribute) -> bool,
534 {
535 }
536}
537
538impl<T: SyntaxNode> SyntaxNode for Spanned<T> {
539 fn span(&self) -> Option<Span> {
540 Some(self.span())
541 }
542
543 fn ident(&self) -> Option<Ident> {
544 self.node().ident()
545 }
546
547 fn attributes(&self) -> &[AttributeNode] {
548 self.node().attributes()
549 }
550
551 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
552 self.node_mut().attributes_mut()
553 }
554
555 fn retain_attributes_mut<F>(&mut self, mut f: F)
556 where
557 F: FnMut(&mut Attribute) -> bool,
558 {
559 self.node_mut().retain_attributes_mut(|v| f(v))
560 }
561}
562
563macro_rules! impl_attrs_struct {
564 () => {
565 fn attributes(&self) -> &[AttributeNode] {
566 &self.attributes
567 }
568 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
569 &mut self.attributes
570 }
571 fn retain_attributes_mut<F>(&mut self, mut f: F)
572 where
573 F: FnMut(&mut Attribute) -> bool,
574 {
575 self.attributes.retain_mut(|v| f(v))
576 }
577 };
578}
579
580macro_rules! impl_attrs_enum {
581 ($($variant: path),* $(,)?) => {
582 fn attributes(&self) -> &[AttributeNode] {
583 match self {
584 $(
585 $variant(x) => &x.attributes,
586 )*
587 #[allow(unreachable_patterns)]
588 _ => &[]
589 }
590 }
591 fn attributes_mut(&mut self) -> &mut [AttributeNode] {
592 match self {
593 $(
594 $variant(x) => &mut x.attributes,
595 )*
596 #[allow(unreachable_patterns)]
597 _ => &mut []
598 }
599 }
600 fn retain_attributes_mut<F>(&mut self, mut f: F)
601 where
602 F: FnMut(&mut Attribute) -> bool,
603 {
604 match self {
605 $(
606 $variant(x) => x.attributes.retain_mut(|v| f(v)),
607 )*
608 #[allow(unreachable_patterns)]
609 _ => {}
610 }
611 }
612 };
613}
614
615#[cfg(feature = "imports")]
616impl SyntaxNode for ImportStatement {
617 #[cfg(feature = "attributes")]
618 impl_attrs_struct! {}
619}
620
621impl SyntaxNode for GlobalDirective {
622 #[cfg(feature = "attributes")]
623 impl_attrs_enum! {
624 GlobalDirective::Diagnostic,
625 GlobalDirective::Enable,
626 GlobalDirective::Requires
627 }
628}
629
630impl SyntaxNode for DiagnosticDirective {
631 #[cfg(feature = "attributes")]
632 impl_attrs_struct! {}
633}
634
635impl SyntaxNode for EnableDirective {
636 #[cfg(feature = "attributes")]
637 impl_attrs_struct! {}
638}
639
640impl SyntaxNode for RequiresDirective {
641 #[cfg(feature = "attributes")]
642 impl_attrs_struct! {}
643}
644
645impl SyntaxNode for GlobalDeclaration {
646 fn ident(&self) -> Option<Ident> {
647 match self {
648 GlobalDeclaration::Void => None,
649 GlobalDeclaration::Declaration(decl) => Some(decl.ident.clone()),
650 GlobalDeclaration::TypeAlias(decl) => Some(decl.ident.clone()),
651 GlobalDeclaration::Struct(decl) => Some(decl.ident.clone()),
652 GlobalDeclaration::Function(decl) => Some(decl.ident.clone()),
653 GlobalDeclaration::ConstAssert(_) => None,
654 }
655 }
656
657 #[cfg(feature = "attributes")]
658 impl_attrs_enum! {
659 GlobalDeclaration::Declaration,
660 GlobalDeclaration::TypeAlias,
661 GlobalDeclaration::Struct,
662 GlobalDeclaration::Function,
663 GlobalDeclaration::ConstAssert,
664 }
665}
666
667impl SyntaxNode for Declaration {
668 fn ident(&self) -> Option<Ident> {
669 Some(self.ident.clone())
670 }
671
672 impl_attrs_struct! {}
673}
674
675impl SyntaxNode for TypeAlias {
676 fn ident(&self) -> Option<Ident> {
677 Some(self.ident.clone())
678 }
679
680 #[cfg(feature = "attributes")]
681 impl_attrs_struct! {}
682}
683
684impl SyntaxNode for Struct {
685 fn ident(&self) -> Option<Ident> {
686 Some(self.ident.clone())
687 }
688
689 #[cfg(feature = "attributes")]
690 impl_attrs_struct! {}
691}
692
693impl SyntaxNode for StructMember {
694 fn ident(&self) -> Option<Ident> {
695 Some(self.ident.clone())
696 }
697
698 impl_attrs_struct! {}
699}
700
701impl SyntaxNode for Function {
702 fn ident(&self) -> Option<Ident> {
703 Some(self.ident.clone())
704 }
705
706 impl_attrs_struct! {}
707}
708
709impl SyntaxNode for FormalParameter {
710 fn ident(&self) -> Option<Ident> {
711 Some(self.ident.clone())
712 }
713
714 impl_attrs_struct! {}
715}
716
717impl SyntaxNode for ConstAssert {
718 #[cfg(feature = "attributes")]
719 impl_attrs_struct! {}
720}
721
722impl SyntaxNode for Expression {}
723impl SyntaxNode for LiteralExpression {}
724impl SyntaxNode for ParenthesizedExpression {}
725impl SyntaxNode for NamedComponentExpression {}
726impl SyntaxNode for IndexingExpression {}
727impl SyntaxNode for UnaryExpression {}
728impl SyntaxNode for BinaryExpression {}
729impl SyntaxNode for FunctionCall {}
730impl SyntaxNode for TypeExpression {}
731
732impl SyntaxNode for Statement {
733 #[cfg(feature = "attributes")]
734 impl_attrs_enum! {
735 Statement::Compound,
736 Statement::Assignment,
737 Statement::Increment,
738 Statement::Decrement,
739 Statement::If,
740 Statement::Switch,
741 Statement::Loop,
742 Statement::For,
743 Statement::While,
744 Statement::Break,
745 Statement::Continue,
746 Statement::Return,
747 Statement::Discard,
748 Statement::FunctionCall,
749 Statement::ConstAssert,
750 Statement::Declaration,
751 }
752}
753
754impl SyntaxNode for CompoundStatement {
755 impl_attrs_struct! {}
756}
757
758impl SyntaxNode for AssignmentStatement {
759 #[cfg(feature = "attributes")]
760 impl_attrs_struct! {}
761}
762
763impl SyntaxNode for IncrementStatement {
764 #[cfg(feature = "attributes")]
765 impl_attrs_struct! {}
766}
767
768impl SyntaxNode for DecrementStatement {
769 #[cfg(feature = "attributes")]
770 impl_attrs_struct! {}
771}
772
773impl SyntaxNode for IfStatement {
774 impl_attrs_struct! {}
775}
776
777impl SyntaxNode for IfClause {}
778
779impl SyntaxNode for ElseIfClause {
780 #[cfg(feature = "attributes")]
781 impl_attrs_struct! {}
782}
783
784impl SyntaxNode for ElseClause {
785 #[cfg(feature = "attributes")]
786 impl_attrs_struct! {}
787}
788
789impl SyntaxNode for SwitchStatement {
790 impl_attrs_struct! {}
791}
792
793impl SyntaxNode for SwitchClause {
794 #[cfg(feature = "attributes")]
795 impl_attrs_struct! {}
796}
797
798impl SyntaxNode for LoopStatement {
799 impl_attrs_struct! {}
800}
801
802impl SyntaxNode for ContinuingStatement {
803 #[cfg(feature = "attributes")]
804 impl_attrs_struct! {}
805}
806
807impl SyntaxNode for BreakIfStatement {
808 #[cfg(feature = "attributes")]
809 impl_attrs_struct! {}
810}
811
812impl SyntaxNode for ForStatement {
813 impl_attrs_struct! {}
814}
815
816impl SyntaxNode for WhileStatement {
817 impl_attrs_struct! {}
818}
819
820impl SyntaxNode for BreakStatement {
821 #[cfg(feature = "attributes")]
822 impl_attrs_struct! {}
823}
824
825impl SyntaxNode for ContinueStatement {
826 #[cfg(feature = "attributes")]
827 impl_attrs_struct! {}
828}
829
830impl SyntaxNode for ReturnStatement {
831 #[cfg(feature = "attributes")]
832 impl_attrs_struct! {}
833}
834
835impl SyntaxNode for DiscardStatement {
836 #[cfg(feature = "attributes")]
837 impl_attrs_struct! {}
838}
839
840impl SyntaxNode for FunctionCallStatement {
841 #[cfg(feature = "attributes")]
842 impl_attrs_struct! {}
843}