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