Fork of daniellemaywood.uk/gleam — Wasm codegen work
42 kB
1411 lines
1use ecow::EcoString;
2use num_bigint::BigInt;
3use vec1::Vec1;
4
5use crate::{
6 analyse::Inferred,
7 ast::{
8 AssignName, Assignment, BinOp, CallArg, Constant, Definition, FunctionLiteralKind, Pattern,
9 RecordBeingUpdated, SrcSpan, Statement, TargetedDefinition, TodoKind, TypeAst,
10 TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, UntypedArg,
11 UntypedAssignment, UntypedClause, UntypedConstant, UntypedConstantBitArraySegment,
12 UntypedCustomType, UntypedDefinition, UntypedExpr, UntypedExprBitArraySegment,
13 UntypedFunction, UntypedImport, UntypedModule, UntypedModuleConstant, UntypedPattern,
14 UntypedPatternBitArraySegment, UntypedRecordUpdateArg, UntypedStatement, UntypedTypeAlias,
15 UntypedUse, UntypedUseAssignment, Use, UseAssignment,
16 },
17 build::Target,
18 type_::error::VariableOrigin,
19};
20
21#[allow(dead_code)]
22pub trait UntypedModuleFolder: TypeAstFolder + UntypedExprFolder {
23 /// You probably don't want to override this method.
24 fn fold_module(&mut self, mut m: UntypedModule) -> UntypedModule {
25 m.definitions = m
26 .definitions
27 .into_iter()
28 .map(|d| {
29 let TargetedDefinition { definition, target } = d;
30 match definition {
31 Definition::Function(f) => {
32 let f = self.fold_function_definition(f, target);
33 let definition = self.walk_function_definition(f);
34 TargetedDefinition { definition, target }
35 }
36
37 Definition::TypeAlias(a) => {
38 let a = self.fold_type_alias(a, target);
39 let definition = self.walk_type_alias(a);
40 TargetedDefinition { definition, target }
41 }
42
43 Definition::CustomType(t) => {
44 let t = self.fold_custom_type(t, target);
45 let definition = self.walk_custom_type(t);
46 TargetedDefinition { definition, target }
47 }
48
49 Definition::Import(i) => {
50 let i = self.fold_import(i, target);
51 let definition = self.walk_import(i);
52 TargetedDefinition { definition, target }
53 }
54
55 Definition::ModuleConstant(c) => {
56 let c = self.fold_module_constant(c, target);
57 let definition = self.walk_module_constant(c);
58 TargetedDefinition { definition, target }
59 }
60 }
61 })
62 .collect();
63 m
64 }
65
66 /// You probably don't want to override this method.
67 fn walk_function_definition(&mut self, mut f: UntypedFunction) -> UntypedDefinition {
68 f.body = f.body.mapped(|s| self.fold_statement(s));
69 f.return_annotation = f.return_annotation.map(|t| self.fold_type(t));
70 f.arguments = f
71 .arguments
72 .into_iter()
73 .map(|mut a| {
74 a.annotation = a.annotation.map(|t| self.fold_type(t));
75 a
76 })
77 .collect();
78 Definition::Function(f)
79 }
80
81 /// You probably don't want to override this method.
82 fn walk_type_alias(&mut self, mut f: UntypedTypeAlias) -> UntypedDefinition {
83 f.type_ast = self.fold_type(f.type_ast);
84 Definition::TypeAlias(f)
85 }
86
87 /// You probably don't want to override this method.
88 fn walk_custom_type(&mut self, mut c: UntypedCustomType) -> UntypedDefinition {
89 c.constructors = c
90 .constructors
91 .into_iter()
92 .map(|mut c| {
93 c.arguments = c
94 .arguments
95 .into_iter()
96 .map(|mut a| {
97 a.ast = self.fold_type(a.ast);
98 a
99 })
100 .collect();
101 c
102 })
103 .collect();
104
105 Definition::CustomType(c)
106 }
107
108 /// You probably don't want to override this method.
109 fn walk_import(&mut self, i: UntypedImport) -> UntypedDefinition {
110 Definition::Import(i)
111 }
112
113 /// You probably don't want to override this method.
114 fn walk_module_constant(&mut self, mut c: UntypedModuleConstant) -> UntypedDefinition {
115 c.annotation = c.annotation.map(|t| self.fold_type(t));
116 c.value = Box::new(self.fold_constant(*c.value));
117 Definition::ModuleConstant(c)
118 }
119
120 fn fold_function_definition(
121 &mut self,
122 f: UntypedFunction,
123 _target: Option<Target>,
124 ) -> UntypedFunction {
125 f
126 }
127
128 fn fold_type_alias(
129 &mut self,
130 f: UntypedTypeAlias,
131 _target: Option<Target>,
132 ) -> UntypedTypeAlias {
133 f
134 }
135
136 fn fold_custom_type(
137 &mut self,
138 c: UntypedCustomType,
139 _target: Option<Target>,
140 ) -> UntypedCustomType {
141 c
142 }
143
144 fn fold_import(&mut self, i: UntypedImport, _target: Option<Target>) -> UntypedImport {
145 i
146 }
147
148 fn fold_module_constant(
149 &mut self,
150 c: UntypedModuleConstant,
151 _target: Option<Target>,
152 ) -> UntypedModuleConstant {
153 c
154 }
155}
156
157#[allow(dead_code)]
158pub trait TypeAstFolder {
159 /// Visit a node and potentially replace it with another node using the
160 /// `fold_*` methods. Afterwards, the `walk` method is called on the new
161 /// node to continue traversing.
162 ///
163 /// You probably don't want to override this method.
164 fn fold_type(&mut self, t: TypeAst) -> TypeAst {
165 let t = self.update_type(t);
166 self.walk_type(t)
167 }
168
169 /// You probably don't want to override this method.
170 fn update_type(&mut self, t: TypeAst) -> TypeAst {
171 match t {
172 TypeAst::Constructor(c) => self.fold_type_constructor(c),
173 TypeAst::Fn(f) => self.fold_type_fn(f),
174 TypeAst::Var(v) => self.fold_type_var(v),
175 TypeAst::Tuple(t) => self.fold_type_tuple(t),
176 TypeAst::Hole(h) => self.fold_type_hole(h),
177 }
178 }
179
180 /// You probably don't want to override this method.
181 fn walk_type(&mut self, t: TypeAst) -> TypeAst {
182 match t {
183 TypeAst::Constructor(mut c) => {
184 c.arguments = self.fold_all_types(c.arguments);
185 TypeAst::Constructor(c)
186 }
187
188 TypeAst::Fn(mut f) => {
189 f.arguments = self.fold_all_types(f.arguments);
190 f.return_ = Box::new(self.fold_type(*f.return_));
191 TypeAst::Fn(f)
192 }
193
194 TypeAst::Tuple(mut t) => {
195 t.elems = self.fold_all_types(t.elems);
196 TypeAst::Tuple(t)
197 }
198
199 TypeAst::Var(_) | TypeAst::Hole(_) => t,
200 }
201 }
202
203 /// You probably don't want to override this method.
204 fn fold_all_types(&mut self, ts: Vec<TypeAst>) -> Vec<TypeAst> {
205 ts.into_iter().map(|t| self.fold_type(t)).collect()
206 }
207
208 fn fold_type_constructor(&mut self, constructor: TypeAstConstructor) -> TypeAst {
209 TypeAst::Constructor(constructor)
210 }
211
212 fn fold_type_fn(&mut self, function: TypeAstFn) -> TypeAst {
213 TypeAst::Fn(function)
214 }
215
216 fn fold_type_tuple(&mut self, tuple: TypeAstTuple) -> TypeAst {
217 TypeAst::Tuple(tuple)
218 }
219
220 fn fold_type_var(&mut self, var: TypeAstVar) -> TypeAst {
221 TypeAst::Var(var)
222 }
223
224 fn fold_type_hole(&mut self, hole: TypeAstHole) -> TypeAst {
225 TypeAst::Hole(hole)
226 }
227}
228
229#[allow(dead_code)]
230pub trait UntypedExprFolder: TypeAstFolder + UntypedConstantFolder + PatternFolder {
231 /// Visit a node and potentially replace it with another node using the
232 /// `fold_*` methods. Afterwards, the `walk` method is called on the new
233 /// node to continue traversing.
234 ///
235 /// You probably don't want to override this method.
236 fn fold_expr(&mut self, t: UntypedExpr) -> UntypedExpr {
237 let t = self.update_expr(t);
238 self.walk_expr(t)
239 }
240
241 /// You probably don't want to override this method.
242 fn update_expr(&mut self, e: UntypedExpr) -> UntypedExpr {
243 match e {
244 UntypedExpr::Var { location, name } => self.fold_var(location, name),
245 UntypedExpr::Int {
246 location,
247 value,
248 int_value,
249 } => self.fold_int(location, value, int_value),
250 UntypedExpr::Float { location, value } => self.fold_float(location, value),
251 UntypedExpr::String { location, value } => self.fold_string(location, value),
252
253 UntypedExpr::Block {
254 location,
255 statements,
256 } => self.fold_block(location, statements),
257
258 UntypedExpr::Fn {
259 location,
260 end_of_head_byte_index,
261 kind,
262 arguments,
263 body,
264 return_annotation,
265 } => self.fold_fn(
266 location,
267 end_of_head_byte_index,
268 kind,
269 arguments,
270 body,
271 return_annotation,
272 ),
273
274 UntypedExpr::List {
275 location,
276 elements,
277 tail,
278 } => self.fold_list(location, elements, tail),
279
280 UntypedExpr::Call {
281 location,
282 fun,
283 arguments,
284 } => self.fold_call(location, fun, arguments),
285
286 UntypedExpr::BinOp {
287 location,
288 name,
289 left,
290 right,
291 } => self.fold_bin_op(location, name, left, right),
292
293 UntypedExpr::PipeLine { expressions } => self.fold_pipe_line(expressions),
294
295 UntypedExpr::Case {
296 location,
297 subjects,
298 clauses,
299 } => self.fold_case(location, subjects, clauses),
300
301 UntypedExpr::FieldAccess {
302 location,
303 label_location,
304 label,
305 container,
306 } => self.fold_field_access(location, label_location, label, container),
307
308 UntypedExpr::Tuple { location, elems } => self.fold_tuple(location, elems),
309
310 UntypedExpr::TupleIndex {
311 location,
312 index,
313 tuple,
314 } => self.fold_tuple_index(location, index, tuple),
315
316 UntypedExpr::Todo {
317 kind,
318 location,
319 message,
320 } => self.fold_todo(kind, location, message),
321
322 UntypedExpr::Panic { location, message } => self.fold_panic(location, message),
323
324 UntypedExpr::BitArray { location, segments } => self.fold_bit_array(location, segments),
325
326 UntypedExpr::RecordUpdate {
327 location,
328 constructor,
329 record,
330 arguments,
331 } => self.fold_record_update(location, constructor, record, arguments),
332
333 UntypedExpr::NegateBool { location, value } => self.fold_negate_bool(location, value),
334
335 UntypedExpr::NegateInt { location, value } => self.fold_negate_int(location, value),
336
337 UntypedExpr::Placeholder { location } => self.fold_placeholder(location),
338 }
339 }
340
341 /// You probably don't want to override this method.
342 fn walk_expr(&mut self, e: UntypedExpr) -> UntypedExpr {
343 match e {
344 UntypedExpr::Int { .. }
345 | UntypedExpr::Var { .. }
346 | UntypedExpr::Float { .. }
347 | UntypedExpr::String { .. }
348 | UntypedExpr::NegateInt { .. }
349 | UntypedExpr::NegateBool { .. }
350 | UntypedExpr::Placeholder { .. } => e,
351
352 UntypedExpr::Todo {
353 kind,
354 location,
355 message,
356 } => UntypedExpr::Todo {
357 kind,
358 location,
359 message: message.map(|msg_expr| Box::new(self.fold_expr(*msg_expr))),
360 },
361
362 UntypedExpr::Panic { location, message } => UntypedExpr::Panic {
363 location,
364 message: message.map(|msg_expr| Box::new(self.fold_expr(*msg_expr))),
365 },
366
367 UntypedExpr::Block {
368 location,
369 statements,
370 } => {
371 let statements = statements.mapped(|s| self.fold_statement(s));
372 UntypedExpr::Block {
373 location,
374 statements,
375 }
376 }
377
378 UntypedExpr::Fn {
379 location,
380 kind,
381 end_of_head_byte_index,
382 arguments,
383 body,
384 return_annotation,
385 } => {
386 let arguments = arguments.into_iter().map(|a| self.fold_arg(a)).collect();
387 let return_annotation = return_annotation.map(|t| self.fold_type(t));
388 let body = body.mapped(|s| self.fold_statement(s));
389 UntypedExpr::Fn {
390 location,
391 end_of_head_byte_index,
392 kind,
393 arguments,
394 body,
395 return_annotation,
396 }
397 }
398
399 UntypedExpr::List {
400 location,
401 elements,
402 tail,
403 } => {
404 let elements = elements.into_iter().map(|e| self.fold_expr(e)).collect();
405 let tail = tail.map(|e| Box::new(self.fold_expr(*e)));
406 UntypedExpr::List {
407 location,
408 elements,
409 tail,
410 }
411 }
412
413 UntypedExpr::Call {
414 location,
415 fun,
416 arguments,
417 } => {
418 let fun = Box::new(self.fold_expr(*fun));
419 let arguments = arguments
420 .into_iter()
421 .map(|mut a| {
422 a.value = self.fold_expr(a.value);
423 a
424 })
425 .collect();
426 UntypedExpr::Call {
427 location,
428 fun,
429 arguments,
430 }
431 }
432
433 UntypedExpr::BinOp {
434 location,
435 name,
436 left,
437 right,
438 } => {
439 let left = Box::new(self.fold_expr(*left));
440 let right = Box::new(self.fold_expr(*right));
441 UntypedExpr::BinOp {
442 location,
443 name,
444 left,
445 right,
446 }
447 }
448
449 UntypedExpr::PipeLine { expressions } => {
450 let expressions = expressions.mapped(|e| self.fold_expr(e));
451 UntypedExpr::PipeLine { expressions }
452 }
453
454 UntypedExpr::Case {
455 location,
456 subjects,
457 clauses,
458 } => {
459 let subjects = subjects.into_iter().map(|e| self.fold_expr(e)).collect();
460 let clauses = clauses.map(|clauses| {
461 clauses
462 .into_iter()
463 .map(|mut c| {
464 c.pattern = c
465 .pattern
466 .into_iter()
467 .map(|p| self.fold_pattern(p))
468 .collect();
469 c.alternative_patterns = c
470 .alternative_patterns
471 .into_iter()
472 .map(|p| p.into_iter().map(|p| self.fold_pattern(p)).collect())
473 .collect();
474 c.then = self.fold_expr(c.then);
475 c
476 })
477 .collect()
478 });
479 UntypedExpr::Case {
480 location,
481 subjects,
482 clauses,
483 }
484 }
485
486 UntypedExpr::FieldAccess {
487 location,
488 label_location,
489 label,
490 container,
491 } => {
492 let container = Box::new(self.fold_expr(*container));
493 UntypedExpr::FieldAccess {
494 location,
495 label_location,
496 label,
497 container,
498 }
499 }
500
501 UntypedExpr::Tuple { location, elems } => {
502 let elems = elems.into_iter().map(|e| self.fold_expr(e)).collect();
503 UntypedExpr::Tuple { location, elems }
504 }
505
506 UntypedExpr::TupleIndex {
507 location,
508 index,
509 tuple,
510 } => {
511 let tuple = Box::new(self.fold_expr(*tuple));
512 UntypedExpr::TupleIndex {
513 location,
514 index,
515 tuple,
516 }
517 }
518
519 UntypedExpr::BitArray { location, segments } => {
520 let segments = segments
521 .into_iter()
522 .map(|mut s| {
523 s.value = Box::new(self.fold_expr(*s.value));
524 s
525 })
526 .collect();
527 UntypedExpr::BitArray { location, segments }
528 }
529
530 UntypedExpr::RecordUpdate {
531 location,
532 constructor,
533 record,
534 arguments,
535 } => {
536 let constructor = Box::new(self.fold_expr(*constructor));
537 let arguments = arguments
538 .into_iter()
539 .map(|mut a| {
540 a.value = self.fold_expr(a.value);
541 a
542 })
543 .collect();
544 UntypedExpr::RecordUpdate {
545 location,
546 constructor,
547 record,
548 arguments,
549 }
550 }
551 }
552 }
553
554 /// You probably don't want to override this method.
555 fn fold_arg(&mut self, arg: UntypedArg) -> UntypedArg {
556 let UntypedArg {
557 location,
558 names,
559 annotation,
560 type_,
561 } = arg;
562 let annotation = annotation.map(|t| self.fold_type(t));
563 UntypedArg {
564 location,
565 names,
566 annotation,
567 type_,
568 }
569 }
570
571 /// You probably don't want to override this method.
572 fn fold_statement(&mut self, s: UntypedStatement) -> UntypedStatement {
573 let s = self.update_statement(s);
574 self.walk_statement(s)
575 }
576
577 /// You probably don't want to override this method.
578 fn update_statement(&mut self, s: UntypedStatement) -> UntypedStatement {
579 match s {
580 Statement::Expression(e) => Statement::Expression(e),
581 Statement::Assignment(a) => Statement::Assignment(self.fold_assignment(a)),
582 Statement::Use(u) => Statement::Use(self.fold_use(u)),
583 }
584 }
585
586 /// You probably don't want to override this method.
587 fn walk_statement(&mut self, s: UntypedStatement) -> UntypedStatement {
588 match s {
589 Statement::Expression(e) => Statement::Expression(self.fold_expr(e)),
590
591 Statement::Assignment(Assignment {
592 location,
593 value,
594 pattern,
595 kind,
596 annotation,
597 }) => {
598 let pattern = self.fold_pattern(pattern);
599 let annotation = annotation.map(|t| self.fold_type(t));
600 let value = Box::new(self.fold_expr(*value));
601 Statement::Assignment(Assignment {
602 location,
603 value,
604 pattern,
605 kind,
606 annotation,
607 })
608 }
609
610 Statement::Use(Use {
611 location,
612 right_hand_side_location,
613 assignments_location,
614 call,
615 assignments,
616 }) => {
617 let assignments = assignments
618 .into_iter()
619 .map(|a| {
620 let mut use_ = self.fold_use_assignment(a);
621 use_.pattern = self.fold_pattern(use_.pattern);
622 use_
623 })
624 .collect();
625 let call = Box::new(self.fold_expr(*call));
626 Statement::Use(Use {
627 location,
628 right_hand_side_location,
629 assignments_location,
630 call,
631 assignments,
632 })
633 }
634 }
635 }
636
637 /// You probably don't want to override this method.
638 fn fold_use_assignment(&mut self, use_: UntypedUseAssignment) -> UntypedUseAssignment {
639 let UseAssignment {
640 location,
641 pattern,
642 annotation,
643 } = use_;
644 let annotation = annotation.map(|t| self.fold_type(t));
645 UseAssignment {
646 location,
647 pattern,
648 annotation,
649 }
650 }
651
652 fn fold_int(&mut self, location: SrcSpan, value: EcoString, int_value: BigInt) -> UntypedExpr {
653 UntypedExpr::Int {
654 location,
655 value,
656 int_value,
657 }
658 }
659
660 fn fold_float(&mut self, location: SrcSpan, value: EcoString) -> UntypedExpr {
661 UntypedExpr::Float { location, value }
662 }
663
664 fn fold_string(&mut self, location: SrcSpan, value: EcoString) -> UntypedExpr {
665 UntypedExpr::String { location, value }
666 }
667
668 fn fold_block(&mut self, location: SrcSpan, statements: Vec1<UntypedStatement>) -> UntypedExpr {
669 UntypedExpr::Block {
670 location,
671 statements,
672 }
673 }
674
675 fn fold_var(&mut self, location: SrcSpan, name: EcoString) -> UntypedExpr {
676 UntypedExpr::Var { location, name }
677 }
678
679 fn fold_fn(
680 &mut self,
681 location: SrcSpan,
682 end_of_head_byte_index: u32,
683 kind: FunctionLiteralKind,
684 arguments: Vec<UntypedArg>,
685 body: Vec1<UntypedStatement>,
686 return_annotation: Option<TypeAst>,
687 ) -> UntypedExpr {
688 UntypedExpr::Fn {
689 location,
690 end_of_head_byte_index,
691 kind,
692 arguments,
693 body,
694 return_annotation,
695 }
696 }
697
698 fn fold_list(
699 &mut self,
700 location: SrcSpan,
701 elements: Vec<UntypedExpr>,
702 tail: Option<Box<UntypedExpr>>,
703 ) -> UntypedExpr {
704 UntypedExpr::List {
705 location,
706 elements,
707 tail,
708 }
709 }
710
711 fn fold_call(
712 &mut self,
713 location: SrcSpan,
714 fun: Box<UntypedExpr>,
715 arguments: Vec<CallArg<UntypedExpr>>,
716 ) -> UntypedExpr {
717 UntypedExpr::Call {
718 location,
719 fun,
720 arguments,
721 }
722 }
723
724 fn fold_bin_op(
725 &mut self,
726 location: SrcSpan,
727 name: BinOp,
728 left: Box<UntypedExpr>,
729 right: Box<UntypedExpr>,
730 ) -> UntypedExpr {
731 UntypedExpr::BinOp {
732 location,
733 name,
734 left,
735 right,
736 }
737 }
738
739 fn fold_pipe_line(&mut self, expressions: Vec1<UntypedExpr>) -> UntypedExpr {
740 UntypedExpr::PipeLine { expressions }
741 }
742
743 fn fold_case(
744 &mut self,
745 location: SrcSpan,
746 subjects: Vec<UntypedExpr>,
747 clauses: Option<Vec<UntypedClause>>,
748 ) -> UntypedExpr {
749 UntypedExpr::Case {
750 location,
751 subjects,
752 clauses,
753 }
754 }
755
756 fn fold_field_access(
757 &mut self,
758 location: SrcSpan,
759 label_location: SrcSpan,
760 label: EcoString,
761 container: Box<UntypedExpr>,
762 ) -> UntypedExpr {
763 UntypedExpr::FieldAccess {
764 location,
765 label_location,
766 label,
767 container,
768 }
769 }
770
771 fn fold_tuple(&mut self, location: SrcSpan, elems: Vec<UntypedExpr>) -> UntypedExpr {
772 UntypedExpr::Tuple { location, elems }
773 }
774
775 fn fold_tuple_index(
776 &mut self,
777 location: SrcSpan,
778 index: u64,
779 tuple: Box<UntypedExpr>,
780 ) -> UntypedExpr {
781 UntypedExpr::TupleIndex {
782 location,
783 index,
784 tuple,
785 }
786 }
787
788 fn fold_todo(
789 &mut self,
790 kind: TodoKind,
791 location: SrcSpan,
792 message: Option<Box<UntypedExpr>>,
793 ) -> UntypedExpr {
794 UntypedExpr::Todo {
795 kind,
796 location,
797 message,
798 }
799 }
800
801 fn fold_panic(&mut self, location: SrcSpan, message: Option<Box<UntypedExpr>>) -> UntypedExpr {
802 UntypedExpr::Panic { location, message }
803 }
804
805 fn fold_bit_array(
806 &mut self,
807 location: SrcSpan,
808 segments: Vec<UntypedExprBitArraySegment>,
809 ) -> UntypedExpr {
810 UntypedExpr::BitArray { location, segments }
811 }
812
813 fn fold_record_update(
814 &mut self,
815 location: SrcSpan,
816 constructor: Box<UntypedExpr>,
817 record: RecordBeingUpdated,
818 arguments: Vec<UntypedRecordUpdateArg>,
819 ) -> UntypedExpr {
820 UntypedExpr::RecordUpdate {
821 location,
822 constructor,
823 record,
824 arguments,
825 }
826 }
827
828 fn fold_negate_bool(&mut self, location: SrcSpan, value: Box<UntypedExpr>) -> UntypedExpr {
829 UntypedExpr::NegateBool { location, value }
830 }
831
832 fn fold_negate_int(&mut self, location: SrcSpan, value: Box<UntypedExpr>) -> UntypedExpr {
833 UntypedExpr::NegateInt { location, value }
834 }
835
836 fn fold_placeholder(&mut self, location: SrcSpan) -> UntypedExpr {
837 UntypedExpr::Placeholder { location }
838 }
839
840 fn fold_assignment(&mut self, assignment: UntypedAssignment) -> UntypedAssignment {
841 assignment
842 }
843
844 fn fold_use(&mut self, use_: UntypedUse) -> UntypedUse {
845 use_
846 }
847}
848
849#[allow(dead_code)]
850pub trait UntypedConstantFolder {
851 /// You probably don't want to override this method.
852 fn fold_constant(&mut self, m: UntypedConstant) -> UntypedConstant {
853 let m = self.update_constant(m);
854 self.walk_constant(m)
855 }
856
857 /// You probably don't want to override this method.
858 fn update_constant(&mut self, m: UntypedConstant) -> UntypedConstant {
859 match m {
860 Constant::Int {
861 location,
862 value,
863 int_value,
864 } => self.fold_constant_int(location, value, int_value),
865
866 Constant::Float { location, value } => self.fold_constant_float(location, value),
867
868 Constant::String { location, value } => self.fold_constant_string(location, value),
869
870 Constant::Tuple { location, elements } => self.fold_constant_tuple(location, elements),
871
872 Constant::List {
873 location,
874 elements,
875 type_: (),
876 } => self.fold_constant_list(location, elements),
877
878 Constant::Record {
879 location,
880 module,
881 name,
882 args,
883 tag: (),
884 type_: (),
885 field_map: _,
886 } => self.fold_constant_record(location, module, name, args),
887
888 Constant::BitArray { location, segments } => {
889 self.fold_constant_bit_array(location, segments)
890 }
891
892 Constant::Var {
893 location,
894 module,
895 name,
896 constructor: _,
897 type_: (),
898 } => self.fold_constant_var(location, module, name),
899
900 Constant::StringConcatenation {
901 location,
902 left,
903 right,
904 } => self.fold_constant_string_concatenation(location, left, right),
905
906 Constant::Invalid {
907 location,
908 type_: (),
909 } => self.fold_constant_invalid(location),
910 }
911 }
912
913 fn fold_constant_int(
914 &mut self,
915 location: SrcSpan,
916 value: EcoString,
917 int_value: BigInt,
918 ) -> UntypedConstant {
919 Constant::Int {
920 location,
921 value,
922 int_value,
923 }
924 }
925
926 fn fold_constant_float(&mut self, location: SrcSpan, value: EcoString) -> UntypedConstant {
927 Constant::Float { location, value }
928 }
929
930 fn fold_constant_string(&mut self, location: SrcSpan, value: EcoString) -> UntypedConstant {
931 Constant::String { location, value }
932 }
933
934 fn fold_constant_tuple(
935 &mut self,
936 location: SrcSpan,
937 elements: Vec<UntypedConstant>,
938 ) -> UntypedConstant {
939 Constant::Tuple { location, elements }
940 }
941
942 fn fold_constant_list(
943 &mut self,
944 location: SrcSpan,
945 elements: Vec<UntypedConstant>,
946 ) -> UntypedConstant {
947 Constant::List {
948 location,
949 elements,
950 type_: (),
951 }
952 }
953
954 fn fold_constant_record(
955 &mut self,
956 location: SrcSpan,
957 module: Option<(EcoString, SrcSpan)>,
958 name: EcoString,
959 args: Vec<CallArg<UntypedConstant>>,
960 ) -> UntypedConstant {
961 Constant::Record {
962 location,
963 module,
964 name,
965 args,
966 tag: (),
967 type_: (),
968 field_map: None,
969 }
970 }
971
972 fn fold_constant_bit_array(
973 &mut self,
974 location: SrcSpan,
975 segments: Vec<UntypedConstantBitArraySegment>,
976 ) -> UntypedConstant {
977 Constant::BitArray { location, segments }
978 }
979
980 fn fold_constant_var(
981 &mut self,
982 location: SrcSpan,
983 module: Option<(EcoString, SrcSpan)>,
984 name: EcoString,
985 ) -> UntypedConstant {
986 Constant::Var {
987 location,
988 module,
989 name,
990 constructor: None,
991 type_: (),
992 }
993 }
994
995 fn fold_constant_string_concatenation(
996 &mut self,
997 location: SrcSpan,
998 left: Box<UntypedConstant>,
999 right: Box<UntypedConstant>,
1000 ) -> UntypedConstant {
1001 Constant::StringConcatenation {
1002 location,
1003 left,
1004 right,
1005 }
1006 }
1007
1008 fn fold_constant_invalid(&mut self, location: SrcSpan) -> UntypedConstant {
1009 Constant::Invalid {
1010 location,
1011 type_: (),
1012 }
1013 }
1014
1015 /// You probably don't want to override this method.
1016 fn walk_constant(&mut self, m: UntypedConstant) -> UntypedConstant {
1017 match m {
1018 Constant::Var { .. }
1019 | Constant::Int { .. }
1020 | Constant::Float { .. }
1021 | Constant::String { .. }
1022 | Constant::Tuple { .. }
1023 | Constant::Invalid { .. } => m,
1024
1025 Constant::List {
1026 location,
1027 elements,
1028 type_,
1029 } => {
1030 let elements = elements
1031 .into_iter()
1032 .map(|e| self.fold_constant(e))
1033 .collect();
1034 Constant::List {
1035 location,
1036 elements,
1037 type_,
1038 }
1039 }
1040
1041 Constant::Record {
1042 location,
1043 module,
1044 name,
1045 args,
1046 tag,
1047 type_,
1048 field_map,
1049 } => {
1050 let args = args
1051 .into_iter()
1052 .map(|mut a| {
1053 a.value = self.fold_constant(a.value);
1054 a
1055 })
1056 .collect();
1057 Constant::Record {
1058 location,
1059 module,
1060 name,
1061 args,
1062 tag,
1063 type_,
1064 field_map,
1065 }
1066 }
1067
1068 Constant::BitArray { location, segments } => {
1069 let segments = segments
1070 .into_iter()
1071 .map(|mut s| {
1072 s.value = Box::new(self.fold_constant(*s.value));
1073 s
1074 })
1075 .collect();
1076 Constant::BitArray { location, segments }
1077 }
1078
1079 Constant::StringConcatenation {
1080 location,
1081 left,
1082 right,
1083 } => {
1084 let left = Box::new(self.fold_constant(*left));
1085 let right = Box::new(self.fold_constant(*right));
1086 Constant::StringConcatenation {
1087 location,
1088 left,
1089 right,
1090 }
1091 }
1092 }
1093 }
1094}
1095
1096#[allow(dead_code)]
1097pub trait PatternFolder {
1098 /// You probably don't want to override this method.
1099 fn fold_pattern(&mut self, m: UntypedPattern) -> UntypedPattern {
1100 let m = self.update_pattern(m);
1101 self.walk_pattern(m)
1102 }
1103
1104 /// You probably don't want to override this method.
1105 fn update_pattern(&mut self, m: UntypedPattern) -> UntypedPattern {
1106 match m {
1107 Pattern::Int {
1108 location,
1109 value,
1110 int_value,
1111 } => self.fold_pattern_int(location, value, int_value),
1112
1113 Pattern::Float { location, value } => self.fold_pattern_float(location, value),
1114
1115 Pattern::String { location, value } => self.fold_pattern_string(location, value),
1116
1117 Pattern::Variable {
1118 location,
1119 name,
1120 type_: (),
1121 origin,
1122 } => self.fold_pattern_var(location, name, origin),
1123
1124 Pattern::VarUsage {
1125 location,
1126 name,
1127 constructor: _,
1128 type_: (),
1129 } => self.fold_pattern_var_usage(location, name),
1130
1131 Pattern::Assign {
1132 name,
1133 location,
1134 pattern,
1135 } => self.fold_pattern_assign(name, location, pattern),
1136
1137 Pattern::Discard {
1138 name,
1139 location,
1140 type_: (),
1141 } => self.fold_pattern_discard(name, location),
1142
1143 Pattern::List {
1144 location,
1145 elements,
1146 tail,
1147 type_: (),
1148 } => self.fold_pattern_list(location, elements, tail),
1149
1150 Pattern::Constructor {
1151 location,
1152 name,
1153 arguments,
1154 module,
1155 spread,
1156 constructor: _,
1157 type_: (),
1158 } => self.fold_pattern_constructor(location, name, arguments, module, spread),
1159
1160 Pattern::Tuple { location, elems } => self.fold_pattern_tuple(location, elems),
1161
1162 Pattern::BitArray { location, segments } => {
1163 self.fold_pattern_bit_array(location, segments)
1164 }
1165
1166 Pattern::StringPrefix {
1167 location,
1168 left_location,
1169 left_side_assignment,
1170 right_location,
1171 left_side_string,
1172 right_side_assignment,
1173 } => self.fold_pattern_string_prefix(
1174 location,
1175 left_location,
1176 left_side_assignment,
1177 right_location,
1178 left_side_string,
1179 right_side_assignment,
1180 ),
1181
1182 Pattern::Invalid { location, .. } => self.fold_pattern_invalid(location),
1183 }
1184 }
1185
1186 fn fold_pattern_int(
1187 &mut self,
1188 location: SrcSpan,
1189 value: EcoString,
1190 int_value: BigInt,
1191 ) -> UntypedPattern {
1192 Pattern::Int {
1193 location,
1194 value,
1195 int_value,
1196 }
1197 }
1198
1199 fn fold_pattern_float(&mut self, location: SrcSpan, value: EcoString) -> UntypedPattern {
1200 Pattern::Float { location, value }
1201 }
1202
1203 fn fold_pattern_string(&mut self, location: SrcSpan, value: EcoString) -> UntypedPattern {
1204 Pattern::String { location, value }
1205 }
1206
1207 fn fold_pattern_var(
1208 &mut self,
1209 location: SrcSpan,
1210 name: EcoString,
1211 origin: VariableOrigin,
1212 ) -> UntypedPattern {
1213 Pattern::Variable {
1214 location,
1215 name,
1216 type_: (),
1217 origin,
1218 }
1219 }
1220
1221 fn fold_pattern_var_usage(&mut self, location: SrcSpan, name: EcoString) -> UntypedPattern {
1222 Pattern::VarUsage {
1223 location,
1224 name,
1225 constructor: None,
1226 type_: (),
1227 }
1228 }
1229
1230 fn fold_pattern_assign(
1231 &mut self,
1232 name: EcoString,
1233 location: SrcSpan,
1234 pattern: Box<UntypedPattern>,
1235 ) -> UntypedPattern {
1236 Pattern::Assign {
1237 name,
1238 location,
1239 pattern,
1240 }
1241 }
1242
1243 fn fold_pattern_discard(&mut self, name: EcoString, location: SrcSpan) -> UntypedPattern {
1244 Pattern::Discard {
1245 name,
1246 location,
1247 type_: (),
1248 }
1249 }
1250
1251 fn fold_pattern_list(
1252 &mut self,
1253 location: SrcSpan,
1254 elements: Vec<UntypedPattern>,
1255 tail: Option<Box<UntypedPattern>>,
1256 ) -> UntypedPattern {
1257 Pattern::List {
1258 location,
1259 elements,
1260 tail,
1261 type_: (),
1262 }
1263 }
1264
1265 fn fold_pattern_constructor(
1266 &mut self,
1267 location: SrcSpan,
1268 name: EcoString,
1269 arguments: Vec<CallArg<UntypedPattern>>,
1270 module: Option<(EcoString, SrcSpan)>,
1271 spread: Option<SrcSpan>,
1272 ) -> UntypedPattern {
1273 Pattern::Constructor {
1274 location,
1275 name,
1276 arguments,
1277 module,
1278 constructor: Inferred::Unknown,
1279 spread,
1280 type_: (),
1281 }
1282 }
1283
1284 fn fold_pattern_tuple(
1285 &mut self,
1286 location: SrcSpan,
1287 elems: Vec<UntypedPattern>,
1288 ) -> UntypedPattern {
1289 Pattern::Tuple { location, elems }
1290 }
1291
1292 fn fold_pattern_bit_array(
1293 &mut self,
1294 location: SrcSpan,
1295 segments: Vec<UntypedPatternBitArraySegment>,
1296 ) -> UntypedPattern {
1297 Pattern::BitArray { location, segments }
1298 }
1299
1300 fn fold_pattern_string_prefix(
1301 &mut self,
1302 location: SrcSpan,
1303 left_location: SrcSpan,
1304 left_side_assignment: Option<(EcoString, SrcSpan)>,
1305 right_location: SrcSpan,
1306 left_side_string: EcoString,
1307 right_side_assignment: AssignName,
1308 ) -> UntypedPattern {
1309 Pattern::StringPrefix {
1310 location,
1311 left_location,
1312 left_side_assignment,
1313 right_location,
1314 left_side_string,
1315 right_side_assignment,
1316 }
1317 }
1318
1319 fn fold_pattern_invalid(&mut self, location: SrcSpan) -> UntypedPattern {
1320 Pattern::Invalid {
1321 location,
1322 type_: (),
1323 }
1324 }
1325
1326 /// You probably don't want to override this method.
1327 fn walk_pattern(&mut self, m: UntypedPattern) -> UntypedPattern {
1328 match m {
1329 Pattern::Int { .. }
1330 | Pattern::Variable { .. }
1331 | Pattern::Float { .. }
1332 | Pattern::String { .. }
1333 | Pattern::Discard { .. }
1334 | Pattern::VarUsage { .. }
1335 | Pattern::StringPrefix { .. }
1336 | Pattern::Invalid { .. } => m,
1337
1338 Pattern::Assign {
1339 name,
1340 location,
1341 pattern,
1342 } => {
1343 let pattern = Box::new(self.fold_pattern(*pattern));
1344 Pattern::Assign {
1345 name,
1346 location,
1347 pattern,
1348 }
1349 }
1350
1351 Pattern::List {
1352 location,
1353 elements,
1354 tail,
1355 type_,
1356 } => {
1357 let elements = elements.into_iter().map(|p| self.fold_pattern(p)).collect();
1358 let tail = tail.map(|p| Box::new(self.fold_pattern(*p)));
1359 Pattern::List {
1360 location,
1361 elements,
1362 tail,
1363 type_,
1364 }
1365 }
1366
1367 Pattern::Constructor {
1368 location,
1369 name,
1370 arguments,
1371 module,
1372 constructor,
1373 spread,
1374 type_,
1375 } => {
1376 let arguments = arguments
1377 .into_iter()
1378 .map(|mut a| {
1379 a.value = self.fold_pattern(a.value);
1380 a
1381 })
1382 .collect();
1383 Pattern::Constructor {
1384 location,
1385 name,
1386 arguments,
1387 module,
1388 constructor,
1389 spread,
1390 type_,
1391 }
1392 }
1393
1394 Pattern::Tuple { location, elems } => {
1395 let elems = elems.into_iter().map(|p| self.fold_pattern(p)).collect();
1396 Pattern::Tuple { location, elems }
1397 }
1398
1399 Pattern::BitArray { location, segments } => {
1400 let segments = segments
1401 .into_iter()
1402 .map(|mut s| {
1403 s.value = Box::new(self.fold_pattern(*s.value));
1404 s
1405 })
1406 .collect();
1407 Pattern::BitArray { location, segments }
1408 }
1409 }
1410 }
1411}