Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / ast_folder.rs
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}