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