1use lasso::{Key, Spur};
27use smallvec::SmallVec;
28
29use gruel_parser::ast::*;
30use gruel_rir::Rir;
31
32pub trait RemapSpurs {
37 fn remap_spurs(&mut self, table: &[Spur]);
38}
39
40impl RemapSpurs for Spur {
45 fn remap_spurs(&mut self, table: &[Spur]) {
46 let idx = self.into_usize();
47 debug_assert!(
48 idx < table.len(),
49 "cached Spur out of remap-table range ({} >= {})",
50 idx,
51 table.len()
52 );
53 *self = table[idx];
54 }
55}
56
57macro_rules! impl_no_op {
61 ($($t:ty),* $(,)?) => {
62 $(
63 impl RemapSpurs for $t {
64 fn remap_spurs(&mut self, _table: &[Spur]) {}
65 }
66 )*
67 };
68}
69
70impl_no_op!(
71 bool,
72 u8,
73 u16,
74 u32,
75 u64,
76 i8,
77 i16,
78 i32,
79 i64,
80 f32,
81 f64,
82 String,
83 gruel_util::Span,
84 gruel_util::FileId,
85 gruel_util::BinOp,
86 gruel_util::UnaryOp,
87 gruel_parser::ast::Doc,
89);
90
91impl<T: RemapSpurs> RemapSpurs for Box<T> {
96 fn remap_spurs(&mut self, table: &[Spur]) {
97 (**self).remap_spurs(table);
98 }
99}
100
101impl<T: RemapSpurs> RemapSpurs for Option<T> {
102 fn remap_spurs(&mut self, table: &[Spur]) {
103 if let Some(v) = self {
104 v.remap_spurs(table);
105 }
106 }
107}
108
109impl<T: RemapSpurs> RemapSpurs for Vec<T> {
110 fn remap_spurs(&mut self, table: &[Spur]) {
111 for v in self {
112 v.remap_spurs(table);
113 }
114 }
115}
116
117impl<T: RemapSpurs, const N: usize> RemapSpurs for SmallVec<[T; N]>
118where
119 [T; N]: smallvec::Array<Item = T>,
120{
121 fn remap_spurs(&mut self, table: &[Spur]) {
122 for v in self.iter_mut() {
123 v.remap_spurs(table);
124 }
125 }
126}
127
128impl RemapSpurs for Ast {
137 fn remap_spurs(&mut self, table: &[Spur]) {
138 self.items.remap_spurs(table);
139 }
140}
141
142impl RemapSpurs for Ident {
143 fn remap_spurs(&mut self, table: &[Spur]) {
144 let Ident { name, span } = self;
149 name.remap_spurs(table);
150 span.remap_spurs(table);
151 }
152}
153
154impl RemapSpurs for Directive {
155 fn remap_spurs(&mut self, table: &[Spur]) {
156 let Directive { name, args, span } = self;
157 name.remap_spurs(table);
158 args.remap_spurs(table);
159 span.remap_spurs(table);
160 }
161}
162
163impl RemapSpurs for DirectiveArg {
164 fn remap_spurs(&mut self, table: &[Spur]) {
165 match self {
166 DirectiveArg::Ident(i) => i.remap_spurs(table),
167 DirectiveArg::String(s) => s.remap_spurs(table),
168 }
169 }
170}
171
172impl RemapSpurs for Item {
173 fn remap_spurs(&mut self, table: &[Spur]) {
174 match self {
175 Item::Function(f) => f.remap_spurs(table),
176 Item::Struct(s) => s.remap_spurs(table),
177 Item::Enum(e) => e.remap_spurs(table),
178 Item::Interface(i) => i.remap_spurs(table),
179 Item::Derive(d) => d.remap_spurs(table),
180 Item::Const(c) => c.remap_spurs(table),
181 Item::LinkExtern(b) => b.remap_spurs(table),
182 Item::Error(_) => {}
183 }
184 }
185}
186
187impl RemapSpurs for gruel_parser::ast::LinkExternBlock {
188 fn remap_spurs(&mut self, table: &[Spur]) {
189 let gruel_parser::ast::LinkExternBlock {
190 doc,
191 library,
192 items,
193 link_mode,
194 span,
195 } = self;
196 doc.remap_spurs(table);
197 library.remap_spurs(table);
198 items.remap_spurs(table);
199 link_mode.remap_spurs(table);
200 span.remap_spurs(table);
201 }
202}
203
204impl RemapSpurs for gruel_parser::ast::LinkMode {
205 fn remap_spurs(&mut self, _table: &[Spur]) {}
206}
207
208impl RemapSpurs for gruel_parser::ast::ExternFn {
209 fn remap_spurs(&mut self, table: &[Spur]) {
210 let gruel_parser::ast::ExternFn {
211 doc,
212 directives,
213 name,
214 params,
215 return_type,
216 span,
217 } = self;
218 doc.remap_spurs(table);
219 directives.remap_spurs(table);
220 name.remap_spurs(table);
221 params.remap_spurs(table);
222 return_type.remap_spurs(table);
223 span.remap_spurs(table);
224 }
225}
226
227impl RemapSpurs for ConstDecl {
228 fn remap_spurs(&mut self, table: &[Spur]) {
229 let ConstDecl {
230 doc,
231 directives,
232 visibility,
233 name,
234 ty,
235 init,
236 span,
237 } = self;
238 doc.remap_spurs(table);
239 directives.remap_spurs(table);
240 visibility.remap_spurs(table);
241 name.remap_spurs(table);
242 ty.remap_spurs(table);
243 init.remap_spurs(table);
244 span.remap_spurs(table);
245 }
246}
247
248impl RemapSpurs for Visibility {
249 fn remap_spurs(&mut self, _table: &[Spur]) {}
250}
251
252impl RemapSpurs for gruel_builtins::Posture {
253 fn remap_spurs(&mut self, _table: &[Spur]) {}
254}
255
256impl RemapSpurs for StructDecl {
257 fn remap_spurs(&mut self, table: &[Spur]) {
258 let StructDecl {
259 doc,
260 directives,
261 visibility,
262 posture,
263 name,
264 fields,
265 methods,
266 span,
267 } = self;
268 doc.remap_spurs(table);
269 directives.remap_spurs(table);
270 visibility.remap_spurs(table);
271 posture.remap_spurs(table);
272 name.remap_spurs(table);
273 fields.remap_spurs(table);
274 methods.remap_spurs(table);
275 span.remap_spurs(table);
276 }
277}
278
279impl RemapSpurs for FieldDecl {
280 fn remap_spurs(&mut self, table: &[Spur]) {
281 let FieldDecl {
282 doc,
283 visibility,
284 name,
285 ty,
286 span,
287 } = self;
288 doc.remap_spurs(table);
289 visibility.remap_spurs(table);
290 name.remap_spurs(table);
291 ty.remap_spurs(table);
292 span.remap_spurs(table);
293 }
294}
295
296impl RemapSpurs for EnumDecl {
297 fn remap_spurs(&mut self, table: &[Spur]) {
298 let EnumDecl {
302 doc,
303 directives,
304 visibility,
305 posture,
306 name,
307 variants,
308 methods,
309 span,
310 } = self;
311 doc.remap_spurs(table);
312 directives.remap_spurs(table);
313 visibility.remap_spurs(table);
314 posture.remap_spurs(table);
315 name.remap_spurs(table);
316 variants.remap_spurs(table);
317 methods.remap_spurs(table);
318 span.remap_spurs(table);
319 }
320}
321
322impl RemapSpurs for EnumVariant {
323 fn remap_spurs(&mut self, table: &[Spur]) {
324 let EnumVariant {
325 doc,
326 name,
327 kind,
328 span,
329 } = self;
330 doc.remap_spurs(table);
331 name.remap_spurs(table);
332 kind.remap_spurs(table);
333 span.remap_spurs(table);
334 }
335}
336
337impl RemapSpurs for EnumVariantKind {
338 fn remap_spurs(&mut self, table: &[Spur]) {
339 match self {
340 EnumVariantKind::Unit => {}
341 EnumVariantKind::Tuple(types) => types.remap_spurs(table),
342 EnumVariantKind::Struct(fields) => fields.remap_spurs(table),
343 }
344 }
345}
346
347impl RemapSpurs for EnumVariantField {
348 fn remap_spurs(&mut self, table: &[Spur]) {
349 let EnumVariantField {
350 doc,
351 visibility,
352 name,
353 ty,
354 span,
355 } = self;
356 doc.remap_spurs(table);
357 visibility.remap_spurs(table);
358 name.remap_spurs(table);
359 ty.remap_spurs(table);
360 span.remap_spurs(table);
361 }
362}
363
364impl RemapSpurs for InterfaceDecl {
365 fn remap_spurs(&mut self, table: &[Spur]) {
366 let InterfaceDecl {
372 doc,
373 directives,
374 visibility,
375 name,
376 methods,
377 span,
378 } = self;
379 doc.remap_spurs(table);
380 directives.remap_spurs(table);
381 visibility.remap_spurs(table);
382 name.remap_spurs(table);
383 methods.remap_spurs(table);
384 span.remap_spurs(table);
385 }
386}
387
388impl RemapSpurs for MethodSig {
389 fn remap_spurs(&mut self, table: &[Spur]) {
390 let MethodSig {
391 doc,
392 directives,
393 is_unchecked,
394 name,
395 receiver,
396 params,
397 return_type,
398 span,
399 } = self;
400 doc.remap_spurs(table);
401 directives.remap_spurs(table);
402 is_unchecked.remap_spurs(table);
403 name.remap_spurs(table);
404 receiver.remap_spurs(table);
405 params.remap_spurs(table);
406 return_type.remap_spurs(table);
407 span.remap_spurs(table);
408 }
409}
410
411impl RemapSpurs for DeriveDecl {
412 fn remap_spurs(&mut self, table: &[Spur]) {
413 let DeriveDecl {
414 doc,
415 name,
416 methods,
417 span,
418 } = self;
419 doc.remap_spurs(table);
420 name.remap_spurs(table);
421 methods.remap_spurs(table);
422 span.remap_spurs(table);
423 }
424}
425
426impl RemapSpurs for Method {
427 fn remap_spurs(&mut self, table: &[Spur]) {
428 let Method {
429 doc,
430 directives,
431 visibility,
432 is_unchecked,
433 name,
434 receiver,
435 params,
436 return_type,
437 body,
438 span,
439 } = self;
440 doc.remap_spurs(table);
441 directives.remap_spurs(table);
442 visibility.remap_spurs(table);
443 is_unchecked.remap_spurs(table);
444 name.remap_spurs(table);
445 receiver.remap_spurs(table);
446 params.remap_spurs(table);
447 return_type.remap_spurs(table);
448 body.remap_spurs(table);
449 span.remap_spurs(table);
450 }
451}
452
453impl RemapSpurs for SelfParam {
454 fn remap_spurs(&mut self, table: &[Spur]) {
455 let SelfParam { kind, span } = self;
456 kind.remap_spurs(table);
457 span.remap_spurs(table);
458 }
459}
460
461impl RemapSpurs for SelfReceiverKind {
462 fn remap_spurs(&mut self, _table: &[Spur]) {}
463}
464
465impl RemapSpurs for Function {
466 fn remap_spurs(&mut self, table: &[Spur]) {
467 let Function {
468 doc,
469 directives,
470 visibility,
471 is_unchecked,
472 name,
473 params,
474 return_type,
475 body,
476 span,
477 } = self;
478 doc.remap_spurs(table);
479 directives.remap_spurs(table);
480 visibility.remap_spurs(table);
481 is_unchecked.remap_spurs(table);
482 name.remap_spurs(table);
483 params.remap_spurs(table);
484 return_type.remap_spurs(table);
485 body.remap_spurs(table);
486 span.remap_spurs(table);
487 }
488}
489
490impl RemapSpurs for ParamMode {
491 fn remap_spurs(&mut self, _table: &[Spur]) {}
492}
493
494impl RemapSpurs for Param {
495 fn remap_spurs(&mut self, table: &[Spur]) {
496 let Param {
497 is_comptime,
498 mode,
499 name,
500 ty,
501 span,
502 } = self;
503 is_comptime.remap_spurs(table);
504 mode.remap_spurs(table);
505 name.remap_spurs(table);
506 ty.remap_spurs(table);
507 span.remap_spurs(table);
508 }
509}
510
511impl RemapSpurs for TypeExpr {
512 fn remap_spurs(&mut self, table: &[Spur]) {
513 match self {
514 TypeExpr::Named(i) => i.remap_spurs(table),
515 TypeExpr::Unit(_) | TypeExpr::Never(_) => {}
516 TypeExpr::Array { element, .. } => element.remap_spurs(table),
517 TypeExpr::AnonymousStruct {
518 directives,
519 fields,
520 methods,
521 ..
522 } => {
523 directives.remap_spurs(table);
524 fields.remap_spurs(table);
525 methods.remap_spurs(table);
526 }
527 TypeExpr::AnonymousEnum {
528 directives,
529 variants,
530 methods,
531 ..
532 } => {
533 directives.remap_spurs(table);
534 variants.remap_spurs(table);
535 methods.remap_spurs(table);
536 }
537 TypeExpr::AnonymousInterface { methods, .. } => methods.remap_spurs(table),
538 TypeExpr::TypeCall { callee, args, .. } => {
539 callee.remap_spurs(table);
540 args.remap_spurs(table);
541 }
542 TypeExpr::Tuple { elems, .. } => elems.remap_spurs(table),
543 }
544 }
545}
546
547impl RemapSpurs for AnonStructField {
548 fn remap_spurs(&mut self, table: &[Spur]) {
549 let AnonStructField {
550 doc,
551 name,
552 ty,
553 span,
554 } = self;
555 doc.remap_spurs(table);
556 name.remap_spurs(table);
557 ty.remap_spurs(table);
558 span.remap_spurs(table);
559 }
560}
561
562impl RemapSpurs for IntLit {
576 fn remap_spurs(&mut self, _table: &[Spur]) {}
577}
578impl RemapSpurs for FloatLit {
579 fn remap_spurs(&mut self, _table: &[Spur]) {}
580}
581impl RemapSpurs for BoolLit {
582 fn remap_spurs(&mut self, _table: &[Spur]) {}
583}
584impl RemapSpurs for CharLit {
585 fn remap_spurs(&mut self, _table: &[Spur]) {}
586}
587impl RemapSpurs for UnitLit {
588 fn remap_spurs(&mut self, _table: &[Spur]) {}
589}
590impl RemapSpurs for NegIntLit {
591 fn remap_spurs(&mut self, _table: &[Spur]) {}
592}
593impl RemapSpurs for SelfExpr {
594 fn remap_spurs(&mut self, _table: &[Spur]) {}
595}
596impl RemapSpurs for BreakExpr {
597 fn remap_spurs(&mut self, _table: &[Spur]) {}
598}
599impl RemapSpurs for ContinueExpr {
600 fn remap_spurs(&mut self, _table: &[Spur]) {}
601}
602impl RemapSpurs for BinaryOp {
603 fn remap_spurs(&mut self, _table: &[Spur]) {}
604}
605impl RemapSpurs for UnaryOp {
606 fn remap_spurs(&mut self, _table: &[Spur]) {}
607}
608impl RemapSpurs for ArgMode {
609 fn remap_spurs(&mut self, _table: &[Spur]) {}
610}
611
612impl RemapSpurs for StringLit {
614 fn remap_spurs(&mut self, table: &[Spur]) {
615 let StringLit { value, span } = self;
616 value.remap_spurs(table);
617 span.remap_spurs(table);
618 }
619}
620
621impl RemapSpurs for BinaryExpr {
622 fn remap_spurs(&mut self, table: &[Spur]) {
623 let BinaryExpr {
624 left,
625 op,
626 right,
627 span,
628 } = self;
629 left.remap_spurs(table);
630 op.remap_spurs(table);
631 right.remap_spurs(table);
632 span.remap_spurs(table);
633 }
634}
635
636impl RemapSpurs for UnaryExpr {
637 fn remap_spurs(&mut self, table: &[Spur]) {
638 let UnaryExpr { op, operand, span } = self;
639 op.remap_spurs(table);
640 operand.remap_spurs(table);
641 span.remap_spurs(table);
642 }
643}
644
645impl RemapSpurs for ParenExpr {
646 fn remap_spurs(&mut self, table: &[Spur]) {
647 let ParenExpr { inner, span } = self;
648 inner.remap_spurs(table);
649 span.remap_spurs(table);
650 }
651}
652
653impl RemapSpurs for BlockExpr {
654 fn remap_spurs(&mut self, table: &[Spur]) {
655 let BlockExpr {
656 statements,
657 expr,
658 span,
659 } = self;
660 statements.remap_spurs(table);
661 expr.remap_spurs(table);
662 span.remap_spurs(table);
663 }
664}
665
666impl RemapSpurs for IfExpr {
667 fn remap_spurs(&mut self, table: &[Spur]) {
668 let IfExpr {
669 cond,
670 then_block,
671 else_block,
672 span,
673 is_comptime,
674 } = self;
675 cond.remap_spurs(table);
676 then_block.remap_spurs(table);
677 else_block.remap_spurs(table);
678 span.remap_spurs(table);
679 is_comptime.remap_spurs(table);
680 }
681}
682
683impl RemapSpurs for MatchExpr {
684 fn remap_spurs(&mut self, table: &[Spur]) {
685 let MatchExpr {
686 scrutinee,
687 arms,
688 span,
689 } = self;
690 scrutinee.remap_spurs(table);
691 arms.remap_spurs(table);
692 span.remap_spurs(table);
693 }
694}
695
696impl RemapSpurs for MatchArm {
697 fn remap_spurs(&mut self, table: &[Spur]) {
698 let MatchArm {
699 pattern,
700 body,
701 span,
702 } = self;
703 pattern.remap_spurs(table);
704 body.remap_spurs(table);
705 span.remap_spurs(table);
706 }
707}
708
709impl RemapSpurs for Pattern {
710 fn remap_spurs(&mut self, table: &[Spur]) {
711 match self {
712 Pattern::Wildcard(_) => {}
713 Pattern::Ident { name, .. } => name.remap_spurs(table),
714 Pattern::Int(_) | Pattern::NegInt(_) | Pattern::Bool(_) => {}
715 Pattern::Path(p) => p.remap_spurs(table),
716 Pattern::DataVariant {
717 base,
718 type_name,
719 variant,
720 fields,
721 ..
722 } => {
723 base.remap_spurs(table);
724 type_name.remap_spurs(table);
725 variant.remap_spurs(table);
726 fields.remap_spurs(table);
727 }
728 Pattern::StructVariant {
729 base,
730 type_name,
731 variant,
732 fields,
733 ..
734 } => {
735 base.remap_spurs(table);
736 type_name.remap_spurs(table);
737 variant.remap_spurs(table);
738 fields.remap_spurs(table);
739 }
740 Pattern::Struct {
741 type_name, fields, ..
742 } => {
743 type_name.remap_spurs(table);
744 fields.remap_spurs(table);
745 }
746 Pattern::Tuple { elems, .. } => elems.remap_spurs(table),
747 Pattern::ComptimeUnrollArm {
748 binding, iterable, ..
749 } => {
750 binding.remap_spurs(table);
751 iterable.remap_spurs(table);
752 }
753 }
754 }
755}
756
757impl RemapSpurs for TupleElemPattern {
758 fn remap_spurs(&mut self, table: &[Spur]) {
759 match self {
760 TupleElemPattern::Pattern(p) => p.remap_spurs(table),
761 TupleElemPattern::Rest(_) => {}
762 }
763 }
764}
765
766impl RemapSpurs for FieldPattern {
767 fn remap_spurs(&mut self, table: &[Spur]) {
768 let FieldPattern {
769 field_name,
770 sub,
771 is_mut,
772 span,
773 } = self;
774 field_name.remap_spurs(table);
775 sub.remap_spurs(table);
776 is_mut.remap_spurs(table);
777 span.remap_spurs(table);
778 }
779}
780
781impl RemapSpurs for PathPattern {
782 fn remap_spurs(&mut self, table: &[Spur]) {
783 let PathPattern {
784 base,
785 type_name,
786 variant,
787 span,
788 } = self;
789 base.remap_spurs(table);
790 type_name.remap_spurs(table);
791 variant.remap_spurs(table);
792 span.remap_spurs(table);
793 }
794}
795
796impl RemapSpurs for CallArg {
797 fn remap_spurs(&mut self, table: &[Spur]) {
798 let CallArg { mode, expr, span } = self;
799 mode.remap_spurs(table);
800 expr.remap_spurs(table);
801 span.remap_spurs(table);
802 }
803}
804
805impl RemapSpurs for CallExpr {
806 fn remap_spurs(&mut self, table: &[Spur]) {
807 let CallExpr { name, args, span } = self;
808 name.remap_spurs(table);
809 args.remap_spurs(table);
810 span.remap_spurs(table);
811 }
812}
813
814impl RemapSpurs for IntrinsicArg {
815 fn remap_spurs(&mut self, table: &[Spur]) {
816 match self {
817 IntrinsicArg::Expr(e) => e.remap_spurs(table),
818 IntrinsicArg::Type(t) => t.remap_spurs(table),
819 }
820 }
821}
822
823impl RemapSpurs for IntrinsicCallExpr {
824 fn remap_spurs(&mut self, table: &[Spur]) {
825 let IntrinsicCallExpr { name, args, span } = self;
826 name.remap_spurs(table);
827 args.remap_spurs(table);
828 span.remap_spurs(table);
829 }
830}
831
832impl RemapSpurs for StructLitExpr {
833 fn remap_spurs(&mut self, table: &[Spur]) {
834 let StructLitExpr {
835 base,
836 name,
837 fields,
838 span,
839 } = self;
840 base.remap_spurs(table);
841 name.remap_spurs(table);
842 fields.remap_spurs(table);
843 span.remap_spurs(table);
844 }
845}
846
847impl RemapSpurs for FieldInit {
848 fn remap_spurs(&mut self, table: &[Spur]) {
849 let FieldInit { name, value, span } = self;
850 name.remap_spurs(table);
851 value.remap_spurs(table);
852 span.remap_spurs(table);
853 }
854}
855
856impl RemapSpurs for TupleExpr {
857 fn remap_spurs(&mut self, table: &[Spur]) {
858 let TupleExpr { elems, span } = self;
859 elems.remap_spurs(table);
860 span.remap_spurs(table);
861 }
862}
863
864impl RemapSpurs for AnonFnExpr {
865 fn remap_spurs(&mut self, table: &[Spur]) {
866 let AnonFnExpr {
867 params,
868 return_type,
869 body,
870 span,
871 } = self;
872 params.remap_spurs(table);
873 return_type.remap_spurs(table);
874 body.remap_spurs(table);
875 span.remap_spurs(table);
876 }
877}
878
879impl RemapSpurs for TupleIndexExpr {
880 fn remap_spurs(&mut self, table: &[Spur]) {
881 let TupleIndexExpr {
882 base,
883 index,
884 span,
885 index_span,
886 } = self;
887 base.remap_spurs(table);
888 index.remap_spurs(table);
889 span.remap_spurs(table);
890 index_span.remap_spurs(table);
891 }
892}
893
894impl RemapSpurs for FieldExpr {
895 fn remap_spurs(&mut self, table: &[Spur]) {
896 let FieldExpr { base, field, span } = self;
897 base.remap_spurs(table);
898 field.remap_spurs(table);
899 span.remap_spurs(table);
900 }
901}
902
903impl RemapSpurs for MethodCallExpr {
904 fn remap_spurs(&mut self, table: &[Spur]) {
905 let MethodCallExpr {
906 receiver,
907 method,
908 args,
909 span,
910 } = self;
911 receiver.remap_spurs(table);
912 method.remap_spurs(table);
913 args.remap_spurs(table);
914 span.remap_spurs(table);
915 }
916}
917
918impl RemapSpurs for ArrayLitExpr {
919 fn remap_spurs(&mut self, table: &[Spur]) {
920 let ArrayLitExpr { elements, span } = self;
921 elements.remap_spurs(table);
922 span.remap_spurs(table);
923 }
924}
925
926impl RemapSpurs for IndexExpr {
927 fn remap_spurs(&mut self, table: &[Spur]) {
928 let IndexExpr { base, index, span } = self;
929 base.remap_spurs(table);
930 index.remap_spurs(table);
931 span.remap_spurs(table);
932 }
933}
934
935impl RemapSpurs for RangeExpr {
936 fn remap_spurs(&mut self, table: &[Spur]) {
937 let RangeExpr { lo, hi, span } = self;
938 lo.remap_spurs(table);
939 hi.remap_spurs(table);
940 span.remap_spurs(table);
941 }
942}
943
944impl RemapSpurs for PathExpr {
945 fn remap_spurs(&mut self, table: &[Spur]) {
946 let PathExpr {
947 base,
948 type_name,
949 variant,
950 span,
951 } = self;
952 base.remap_spurs(table);
953 type_name.remap_spurs(table);
954 variant.remap_spurs(table);
955 span.remap_spurs(table);
956 }
957}
958
959impl RemapSpurs for EnumStructLitExpr {
960 fn remap_spurs(&mut self, table: &[Spur]) {
961 let EnumStructLitExpr {
962 base,
963 type_name,
964 variant,
965 fields,
966 span,
967 } = self;
968 base.remap_spurs(table);
969 type_name.remap_spurs(table);
970 variant.remap_spurs(table);
971 fields.remap_spurs(table);
972 span.remap_spurs(table);
973 }
974}
975
976impl RemapSpurs for AssocFnCallExpr {
977 fn remap_spurs(&mut self, table: &[Spur]) {
978 let AssocFnCallExpr {
979 base,
980 type_name,
981 type_args,
982 function,
983 args,
984 span,
985 } = self;
986 base.remap_spurs(table);
987 type_name.remap_spurs(table);
988 type_args.remap_spurs(table);
989 function.remap_spurs(table);
990 args.remap_spurs(table);
991 span.remap_spurs(table);
992 }
993}
994
995impl RemapSpurs for ComptimeBlockExpr {
996 fn remap_spurs(&mut self, table: &[Spur]) {
997 let ComptimeBlockExpr { expr, span } = self;
998 expr.remap_spurs(table);
999 span.remap_spurs(table);
1000 }
1001}
1002
1003impl RemapSpurs for ComptimeUnrollForExpr {
1004 fn remap_spurs(&mut self, table: &[Spur]) {
1005 let ComptimeUnrollForExpr {
1006 binding,
1007 iterable,
1008 body,
1009 span,
1010 } = self;
1011 binding.remap_spurs(table);
1012 iterable.remap_spurs(table);
1013 body.remap_spurs(table);
1014 span.remap_spurs(table);
1015 }
1016}
1017
1018impl RemapSpurs for CheckedBlockExpr {
1019 fn remap_spurs(&mut self, table: &[Spur]) {
1020 let CheckedBlockExpr { expr, span } = self;
1021 expr.remap_spurs(table);
1022 span.remap_spurs(table);
1023 }
1024}
1025
1026impl RemapSpurs for TypeLitExpr {
1027 fn remap_spurs(&mut self, table: &[Spur]) {
1028 let TypeLitExpr { type_expr, span } = self;
1029 type_expr.remap_spurs(table);
1030 span.remap_spurs(table);
1031 }
1032}
1033
1034impl RemapSpurs for WhileExpr {
1035 fn remap_spurs(&mut self, table: &[Spur]) {
1036 let WhileExpr { cond, body, span } = self;
1037 cond.remap_spurs(table);
1038 body.remap_spurs(table);
1039 span.remap_spurs(table);
1040 }
1041}
1042
1043impl RemapSpurs for ForExpr {
1044 fn remap_spurs(&mut self, table: &[Spur]) {
1045 let ForExpr {
1046 binding,
1047 is_mut,
1048 iterable,
1049 body,
1050 span,
1051 } = self;
1052 binding.remap_spurs(table);
1053 is_mut.remap_spurs(table);
1054 iterable.remap_spurs(table);
1055 body.remap_spurs(table);
1056 span.remap_spurs(table);
1057 }
1058}
1059
1060impl RemapSpurs for LoopExpr {
1061 fn remap_spurs(&mut self, table: &[Spur]) {
1062 let LoopExpr { body, span } = self;
1063 body.remap_spurs(table);
1064 span.remap_spurs(table);
1065 }
1066}
1067
1068impl RemapSpurs for ReturnExpr {
1069 fn remap_spurs(&mut self, table: &[Spur]) {
1070 let ReturnExpr { value, span } = self;
1071 value.remap_spurs(table);
1072 span.remap_spurs(table);
1073 }
1074}
1075
1076impl RemapSpurs for Expr {
1077 fn remap_spurs(&mut self, table: &[Spur]) {
1078 match self {
1079 Expr::Int(_) | Expr::Float(_) | Expr::Bool(_) | Expr::Char(_) | Expr::Unit(_) => {}
1080 Expr::String(s) => s.remap_spurs(table),
1081 Expr::Ident(i) => i.remap_spurs(table),
1082 Expr::Binary(b) => b.remap_spurs(table),
1083 Expr::Unary(u) => u.remap_spurs(table),
1084 Expr::Paren(p) => p.remap_spurs(table),
1085 Expr::Block(b) => b.remap_spurs(table),
1086 Expr::If(i) => i.remap_spurs(table),
1087 Expr::Match(m) => m.remap_spurs(table),
1088 Expr::While(w) => w.remap_spurs(table),
1089 Expr::For(f) => f.remap_spurs(table),
1090 Expr::Loop(l) => l.remap_spurs(table),
1091 Expr::Call(c) => c.remap_spurs(table),
1092 Expr::Break(_) | Expr::Continue(_) => {}
1093 Expr::Return(r) => r.remap_spurs(table),
1094 Expr::StructLit(s) => s.remap_spurs(table),
1095 Expr::Field(f) => f.remap_spurs(table),
1096 Expr::MethodCall(m) => m.remap_spurs(table),
1097 Expr::IntrinsicCall(i) => i.remap_spurs(table),
1098 Expr::ArrayLit(a) => a.remap_spurs(table),
1099 Expr::Index(i) => i.remap_spurs(table),
1100 Expr::Path(p) => p.remap_spurs(table),
1101 Expr::EnumStructLit(e) => e.remap_spurs(table),
1102 Expr::AssocFnCall(a) => a.remap_spurs(table),
1103 Expr::SelfExpr(_) => {}
1104 Expr::Comptime(c) => c.remap_spurs(table),
1105 Expr::ComptimeUnrollFor(c) => c.remap_spurs(table),
1106 Expr::Checked(c) => c.remap_spurs(table),
1107 Expr::TypeLit(t) => t.remap_spurs(table),
1108 Expr::Tuple(t) => t.remap_spurs(table),
1109 Expr::TupleIndex(t) => t.remap_spurs(table),
1110 Expr::Range(r) => r.remap_spurs(table),
1111 Expr::AnonFn(a) => a.remap_spurs(table),
1112 Expr::Error(_) => {}
1113 }
1114 }
1115}
1116
1117impl RemapSpurs for Statement {
1118 fn remap_spurs(&mut self, table: &[Spur]) {
1119 match self {
1120 Statement::Let(l) => l.remap_spurs(table),
1121 Statement::Assign(a) => a.remap_spurs(table),
1122 Statement::Expr(e) => e.remap_spurs(table),
1123 }
1124 }
1125}
1126
1127impl RemapSpurs for LetStatement {
1128 fn remap_spurs(&mut self, table: &[Spur]) {
1129 let LetStatement {
1130 directives,
1131 is_mut,
1132 pattern,
1133 ty,
1134 init,
1135 span,
1136 } = self;
1137 directives.remap_spurs(table);
1138 is_mut.remap_spurs(table);
1139 pattern.remap_spurs(table);
1140 ty.remap_spurs(table);
1141 init.remap_spurs(table);
1142 span.remap_spurs(table);
1143 }
1144}
1145
1146impl RemapSpurs for AssignStatement {
1147 fn remap_spurs(&mut self, table: &[Spur]) {
1148 let AssignStatement {
1149 target,
1150 value,
1151 span,
1152 } = self;
1153 target.remap_spurs(table);
1154 value.remap_spurs(table);
1155 span.remap_spurs(table);
1156 }
1157}
1158
1159impl RemapSpurs for AssignTarget {
1160 fn remap_spurs(&mut self, table: &[Spur]) {
1161 match self {
1162 AssignTarget::Var(i) => i.remap_spurs(table),
1163 AssignTarget::Field(f) => f.remap_spurs(table),
1164 AssignTarget::Index(i) => i.remap_spurs(table),
1165 }
1166 }
1167}
1168
1169impl RemapSpurs for Rir {
1178 fn remap_spurs(&mut self, _table: &[Spur]) {
1179 debug_assert!(
1180 false,
1181 "RemapSpurs::Rir not yet implemented — Phase 2b stub. \
1182 Cache pipeline currently regenerates RIR from cached AST \
1183 rather than serializing RIR, so this walker should not \
1184 be reached."
1185 );
1186 }
1187}
1188
1189#[cfg(test)]
1190mod tests {
1191 use super::*;
1192 use gruel_util::Span;
1193
1194 #[test]
1195 fn ident_remap_substitutes_spur() {
1196 let table = vec![
1197 Spur::try_from_usize(7).unwrap(),
1198 Spur::try_from_usize(8).unwrap(),
1199 ];
1200 let mut id = Ident {
1201 name: Spur::try_from_usize(1).unwrap(),
1202 span: Span::default(),
1203 };
1204 id.remap_spurs(&table);
1205 assert_eq!(id.name, Spur::try_from_usize(8).unwrap());
1206 }
1207
1208 #[test]
1209 fn vec_of_idents_remaps_each() {
1210 let table = vec![
1211 Spur::try_from_usize(100).unwrap(),
1212 Spur::try_from_usize(200).unwrap(),
1213 ];
1214 let mut idents = vec![
1215 Ident {
1216 name: Spur::try_from_usize(0).unwrap(),
1217 span: Span::default(),
1218 },
1219 Ident {
1220 name: Spur::try_from_usize(1).unwrap(),
1221 span: Span::default(),
1222 },
1223 ];
1224 idents.remap_spurs(&table);
1225 assert_eq!(idents[0].name, Spur::try_from_usize(100).unwrap());
1226 assert_eq!(idents[1].name, Spur::try_from_usize(200).unwrap());
1227 }
1228
1229 #[test]
1230 fn empty_ast_remap_is_noop() {
1231 let mut ast = Ast {
1232 module_doc: None,
1233 items: Vec::new(),
1234 };
1235 ast.remap_spurs(&[]);
1236 assert!(ast.items.is_empty());
1237 }
1238
1239 #[test]
1240 fn nested_expr_remap_substitutes_idents_at_every_level() {
1241 use gruel_parser::ast::{
1242 BinaryExpr, BinaryOp, BlockExpr, CallArg, CallExpr, Function, IntLit, Param, ParamMode,
1243 Statement, TypeExpr, Visibility,
1244 };
1245 use smallvec::smallvec;
1246
1247 let s = |i: usize| Spur::try_from_usize(i).unwrap();
1255 let id = |sp: Spur| Ident {
1256 name: sp,
1257 span: Span::default(),
1258 };
1259
1260 let body_call = Expr::Call(CallExpr {
1261 name: id(s(4)),
1262 args: vec![
1263 CallArg {
1264 mode: ArgMode::Normal,
1265 expr: Expr::Ident(id(s(1))),
1266 span: Span::default(),
1267 },
1268 CallArg {
1269 mode: ArgMode::Normal,
1270 expr: Expr::Ident(id(s(3))),
1271 span: Span::default(),
1272 },
1273 ],
1274 span: Span::default(),
1275 });
1276
1277 let body = Box::new(Expr::Block(BlockExpr {
1278 statements: vec![Statement::Expr(Expr::Binary(BinaryExpr {
1279 left: Box::new(Expr::Ident(id(s(1)))),
1280 op: BinaryOp::Add,
1281 right: Box::new(Expr::Int(IntLit {
1282 value: 1,
1283 span: Span::default(),
1284 })),
1285 span: Span::default(),
1286 }))],
1287 expr: Box::new(body_call),
1288 span: Span::default(),
1289 }));
1290
1291 let mut ast = Ast {
1292 module_doc: None,
1293 items: vec![Item::Function(Function {
1294 doc: None,
1295 directives: smallvec![],
1296 visibility: Visibility::Public,
1297 is_unchecked: false,
1298 name: id(s(0)),
1299 params: vec![
1300 Param {
1301 is_comptime: false,
1302 mode: ParamMode::Normal,
1303 name: id(s(1)),
1304 ty: TypeExpr::Named(id(s(2))),
1305 span: Span::default(),
1306 },
1307 Param {
1308 is_comptime: false,
1309 mode: ParamMode::Normal,
1310 name: id(s(3)),
1311 ty: TypeExpr::Named(id(s(2))),
1312 span: Span::default(),
1313 },
1314 ],
1315 return_type: Some(TypeExpr::Named(id(s(2)))),
1316 body: Expr::Block(BlockExpr {
1317 statements: Vec::new(),
1318 expr: body,
1319 span: Span::default(),
1320 }),
1321 span: Span::default(),
1322 })],
1323 };
1324
1325 let table: Vec<Spur> = (0..5).map(|i| s(i + 10)).collect();
1327 ast.remap_spurs(&table);
1328
1329 fn collect_idents(e: &Expr, out: &mut Vec<Spur>) {
1332 match e {
1333 Expr::Ident(i) => out.push(i.name),
1334 Expr::Binary(b) => {
1335 collect_idents(&b.left, out);
1336 collect_idents(&b.right, out);
1337 }
1338 Expr::Call(c) => {
1339 out.push(c.name.name);
1340 for a in &c.args {
1341 collect_idents(&a.expr, out);
1342 }
1343 }
1344 Expr::Block(b) => {
1345 for s in &b.statements {
1346 if let Statement::Expr(e) = s {
1347 collect_idents(e, out);
1348 }
1349 }
1350 collect_idents(&b.expr, out);
1351 }
1352 _ => {}
1353 }
1354 }
1355
1356 let Item::Function(f) = &ast.items[0] else {
1357 panic!()
1358 };
1359 assert_eq!(f.name.name, s(10));
1360 assert_eq!(f.params[0].name.name, s(11));
1361 assert_eq!(f.params[1].name.name, s(13));
1362 let mut idents = Vec::new();
1363 collect_idents(&f.body, &mut idents);
1364 assert!(
1367 idents.iter().all(|sp| sp.into_usize() >= 10),
1368 "expected every Spur to be in remapped range, got {:?}",
1369 idents
1370 );
1371 }
1372}