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