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