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 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}