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 / tests.rs
32 kB 1169 lines
1use std::sync::Arc; 2 3use camino::Utf8PathBuf; 4use ecow::EcoString; 5 6use crate::analyse::TargetSupport; 7use crate::build::{ExpressionPosition, Origin, Target}; 8use crate::config::PackageConfig; 9use crate::line_numbers::LineNumbers; 10use crate::type_::error::{VariableDeclaration, VariableOrigin, VariableSyntax}; 11use crate::type_::expression::{FunctionDefinition, Purity}; 12use crate::type_::{Deprecation, PRELUDE_MODULE_NAME, Problems}; 13use crate::warning::WarningEmitter; 14use crate::{ 15 ast::{SrcSpan, TypedExpr}, 16 build::Located, 17 type_::{ 18 self, AccessorsMap, EnvironmentArguments, ExprTyper, FieldMap, ModuleValueConstructor, 19 RecordAccessor, Type, ValueConstructor, ValueConstructorVariant, 20 }, 21 uid::UniqueIdGenerator, 22 warning::TypeWarningEmitter, 23}; 24 25use super::{Publicity, Statement, TypedModule, TypedStatement}; 26 27fn compile_module(src: &str) -> TypedModule { 28 use crate::type_::build_prelude; 29 let parsed = 30 crate::parse::parse_module(Utf8PathBuf::from("test/path"), src, &WarningEmitter::null()) 31 .expect("syntax error"); 32 let ast = parsed.module; 33 let ids = UniqueIdGenerator::new(); 34 let mut config = PackageConfig::default(); 35 config.name = "thepackage".into(); 36 let mut modules = im::HashMap::new(); 37 // DUPE: preludeinsertion 38 // TODO: Currently we do this here and also in the tests. It would be better 39 // to have one place where we create all this required state for use in each 40 // place. 41 let _ = modules.insert(PRELUDE_MODULE_NAME.into(), build_prelude(&ids)); 42 let line_numbers = LineNumbers::new(src); 43 let mut config = PackageConfig::default(); 44 config.name = "thepackage".into(); 45 46 crate::analyse::ModuleAnalyzerConstructor::<()> { 47 target: Target::Erlang, 48 ids: &ids, 49 origin: Origin::Src, 50 importable_modules: &modules, 51 warnings: &TypeWarningEmitter::null(), 52 direct_dependencies: &std::collections::HashMap::new(), 53 dev_dependencies: &std::collections::HashSet::new(), 54 target_support: TargetSupport::Enforced, 55 package_config: &config, 56 } 57 .infer_module(ast, line_numbers, "".into()) 58 .expect("should successfully infer") 59} 60 61fn get_bare_expression(statement: &TypedStatement) -> &TypedExpr { 62 match statement { 63 Statement::Expression(expression) => expression, 64 Statement::Use(_) | Statement::Assignment(_) | Statement::Assert(_) => { 65 panic!("Expected expression, got {statement:?}") 66 } 67 } 68} 69 70fn compile_expression(src: &str) -> TypedStatement { 71 let ast = crate::parse::parse_statement_sequence(src).expect("syntax error"); 72 73 let mut modules = im::HashMap::new(); 74 let ids = UniqueIdGenerator::new(); 75 // DUPE: preludeinsertion 76 // TODO: Currently we do this here and also in the tests. It would be better 77 // to have one place where we create all this required state for use in each 78 // place. 79 let _ = modules.insert(PRELUDE_MODULE_NAME.into(), type_::build_prelude(&ids)); 80 let dev_dependencies = std::collections::HashSet::new(); 81 82 let mut environment = EnvironmentArguments { 83 ids, 84 current_package: "thepackage".into(), 85 gleam_version: None, 86 current_module: "mymod".into(), 87 target: Target::Erlang, 88 importable_modules: &modules, 89 target_support: TargetSupport::Enforced, 90 current_origin: Origin::Src, 91 dev_dependencies: &dev_dependencies, 92 } 93 .build(); 94 95 // Insert a cat record to use in the tests 96 let cat_type = Arc::new(Type::Named { 97 publicity: Publicity::Public, 98 package: "mypackage".into(), 99 module: "mymod".into(), 100 name: "Cat".into(), 101 arguments: vec![], 102 inferred_variant: None, 103 }); 104 let variant = ValueConstructorVariant::Record { 105 documentation: Some("wibble".into()), 106 variants_count: 1, 107 name: "Cat".into(), 108 arity: 2, 109 location: SrcSpan { start: 12, end: 15 }, 110 field_map: Some(FieldMap { 111 arity: 2, 112 fields: [("name".into(), 0), ("age".into(), 1)].into(), 113 }), 114 module: "mymod".into(), 115 variant_index: 0, 116 }; 117 environment.insert_variable( 118 "Cat".into(), 119 variant, 120 type_::fn_(vec![type_::string(), type_::int()], cat_type.clone()), 121 Publicity::Public, 122 Deprecation::NotDeprecated, 123 ); 124 125 let accessors = [ 126 ( 127 "name".into(), 128 RecordAccessor { 129 index: 0, 130 label: "name".into(), 131 type_: type_::string(), 132 }, 133 ), 134 ( 135 "age".into(), 136 RecordAccessor { 137 index: 1, 138 label: "age".into(), 139 type_: type_::int(), 140 }, 141 ), 142 ]; 143 144 environment.insert_accessors( 145 "Cat".into(), 146 AccessorsMap { 147 publicity: Publicity::Public, 148 type_: cat_type, 149 shared_accessors: accessors.clone().into(), 150 variant_specific_accessors: vec![accessors.into()], 151 }, 152 ); 153 let mut problems = Problems::new(); 154 ExprTyper::new( 155 &mut environment, 156 FunctionDefinition { 157 has_body: true, 158 has_erlang_external: false, 159 has_javascript_external: false, 160 }, 161 &mut problems, 162 ) 163 .infer_statements(ast) 164 .first() 165 .clone() 166} 167 168#[test] 169fn find_node_todo() { 170 let statement = compile_expression(r#" todo "#); 171 let expr = get_bare_expression(&statement); 172 assert_eq!(expr.find_node(0), None); 173 assert_eq!( 174 expr.find_node(1), 175 Some(Located::Expression { 176 expression: expr, 177 position: ExpressionPosition::Expression 178 }) 179 ); 180 assert_eq!( 181 expr.find_node(4), 182 Some(Located::Expression { 183 expression: expr, 184 position: ExpressionPosition::Expression 185 }) 186 ); 187 assert_eq!( 188 expr.find_node(5), 189 Some(Located::Expression { 190 expression: expr, 191 position: ExpressionPosition::Expression 192 }) 193 ); 194 assert_eq!(expr.find_node(6), None); 195} 196 197#[test] 198fn find_node_todo_with_string() { 199 let statement = compile_expression(r#" todo as "ok" "#); 200 let expr = get_bare_expression(&statement); 201 let message = TypedExpr::String { 202 location: SrcSpan { start: 9, end: 13 }, 203 type_: type_::string(), 204 value: "ok".into(), 205 }; 206 207 assert_eq!(expr.find_node(0), None); 208 assert_eq!( 209 expr.find_node(1), 210 Some(Located::Expression { 211 expression: expr, 212 position: ExpressionPosition::Expression 213 }) 214 ); 215 assert_eq!( 216 expr.find_node(12), 217 Some(Located::Expression { 218 expression: &message, 219 position: ExpressionPosition::Expression 220 }) 221 ); 222 assert_eq!( 223 expr.find_node(13), 224 Some(Located::Expression { 225 expression: &message, 226 position: ExpressionPosition::Expression 227 }) 228 ); 229 assert_eq!(expr.find_node(14), None); 230} 231 232#[test] 233fn find_node_string() { 234 let statement = compile_expression(r#" "ok" "#); 235 let expr = get_bare_expression(&statement); 236 assert_eq!(expr.find_node(0), None); 237 assert_eq!( 238 expr.find_node(1), 239 Some(Located::Expression { 240 expression: expr, 241 position: ExpressionPosition::Expression 242 }) 243 ); 244 assert_eq!( 245 expr.find_node(4), 246 Some(Located::Expression { 247 expression: expr, 248 position: ExpressionPosition::Expression 249 }) 250 ); 251 assert_eq!( 252 expr.find_node(5), 253 Some(Located::Expression { 254 expression: expr, 255 position: ExpressionPosition::Expression 256 }) 257 ); 258 assert_eq!(expr.find_node(6), None); 259} 260 261#[test] 262fn find_node_float() { 263 let statement = compile_expression(r#" 1.02 "#); 264 let expr = get_bare_expression(&statement); 265 assert_eq!(expr.find_node(0), None); 266 assert_eq!( 267 expr.find_node(1), 268 Some(Located::Expression { 269 expression: expr, 270 position: ExpressionPosition::Expression 271 }) 272 ); 273 assert_eq!( 274 expr.find_node(4), 275 Some(Located::Expression { 276 expression: expr, 277 position: ExpressionPosition::Expression 278 }) 279 ); 280 assert_eq!( 281 expr.find_node(5), 282 Some(Located::Expression { 283 expression: expr, 284 position: ExpressionPosition::Expression 285 }) 286 ); 287 assert_eq!(expr.find_node(6), None); 288} 289 290#[test] 291fn find_node_int() { 292 let statement = compile_expression(r#" 1302 "#); 293 let expr = get_bare_expression(&statement); 294 assert_eq!(expr.find_node(0), None); 295 assert_eq!( 296 expr.find_node(1), 297 Some(Located::Expression { 298 expression: expr, 299 position: ExpressionPosition::Expression 300 }) 301 ); 302 assert_eq!( 303 expr.find_node(4), 304 Some(Located::Expression { 305 expression: expr, 306 position: ExpressionPosition::Expression 307 }) 308 ); 309 assert_eq!( 310 expr.find_node(5), 311 Some(Located::Expression { 312 expression: expr, 313 position: ExpressionPosition::Expression 314 }) 315 ); 316 assert_eq!(expr.find_node(6), None); 317} 318 319#[test] 320fn find_node_var() { 321 let statement = compile_expression( 322 r#"{let wibble = 1 323wibble}"#, 324 ); 325 let expr = get_bare_expression(&statement); 326 327 let int1 = TypedExpr::Int { 328 location: SrcSpan { start: 14, end: 15 }, 329 value: "1".into(), 330 int_value: 1.into(), 331 type_: type_::int(), 332 }; 333 334 let var = TypedExpr::Var { 335 location: SrcSpan { start: 16, end: 22 }, 336 constructor: ValueConstructor { 337 deprecation: Deprecation::NotDeprecated, 338 publicity: Publicity::Private, 339 variant: ValueConstructorVariant::LocalVariable { 340 location: SrcSpan { start: 5, end: 11 }, 341 origin: VariableOrigin { 342 syntax: VariableSyntax::Variable("wibble".into()), 343 declaration: VariableDeclaration::LetPattern, 344 }, 345 }, 346 type_: type_::int(), 347 }, 348 name: "wibble".into(), 349 }; 350 351 assert_eq!( 352 expr.find_node(15), 353 Some(Located::Expression { 354 expression: &int1, 355 position: ExpressionPosition::Expression 356 }) 357 ); 358 assert_eq!( 359 expr.find_node(16), 360 Some(Located::Expression { 361 expression: &var, 362 position: ExpressionPosition::Expression 363 }) 364 ); 365 assert_eq!( 366 expr.find_node(21), 367 Some(Located::Expression { 368 expression: &var, 369 position: ExpressionPosition::Expression 370 }) 371 ); 372 assert_eq!( 373 expr.find_node(22), 374 Some(Located::Expression { 375 expression: &var, 376 position: ExpressionPosition::Expression 377 }) 378 ); 379} 380 381#[test] 382fn find_node_sequence() { 383 let block = compile_expression(r#"{ 1 2 3 }"#); 384 assert!(block.find_node(0).is_none()); 385 assert!(block.find_node(1).is_none()); 386 assert!(block.find_node(2).is_some()); 387 assert!(block.find_node(3).is_some()); 388 assert!(block.find_node(4).is_some()); 389 assert!(block.find_node(5).is_some()); 390 assert!(block.find_node(6).is_some()); 391 assert!(block.find_node(7).is_some()); 392} 393 394#[test] 395fn find_node_list() { 396 let statement = compile_expression(r#"[1, 2, 3]"#); 397 let list = get_bare_expression(&statement); 398 399 let int1 = TypedExpr::Int { 400 location: SrcSpan { start: 1, end: 2 }, 401 type_: type_::int(), 402 value: "1".into(), 403 int_value: 1.into(), 404 }; 405 let int2 = TypedExpr::Int { 406 location: SrcSpan { start: 4, end: 5 }, 407 type_: type_::int(), 408 value: "2".into(), 409 int_value: 2.into(), 410 }; 411 let int3 = TypedExpr::Int { 412 location: SrcSpan { start: 7, end: 8 }, 413 type_: type_::int(), 414 value: "3".into(), 415 int_value: 3.into(), 416 }; 417 418 assert_eq!( 419 list.find_node(0), 420 Some(Located::Expression { 421 expression: list, 422 position: ExpressionPosition::Expression 423 }) 424 ); 425 assert_eq!( 426 list.find_node(1), 427 Some(Located::Expression { 428 expression: &int1, 429 position: ExpressionPosition::Expression 430 }) 431 ); 432 assert_eq!( 433 list.find_node(2), 434 Some(Located::Expression { 435 expression: &int1, 436 position: ExpressionPosition::Expression 437 }) 438 ); 439 assert_eq!( 440 list.find_node(3), 441 Some(Located::Expression { 442 expression: list, 443 position: ExpressionPosition::Expression 444 }) 445 ); 446 assert_eq!( 447 list.find_node(4), 448 Some(Located::Expression { 449 expression: &int2, 450 position: ExpressionPosition::Expression 451 }) 452 ); 453 assert_eq!( 454 list.find_node(5), 455 Some(Located::Expression { 456 expression: &int2, 457 position: ExpressionPosition::Expression 458 }) 459 ); 460 assert_eq!( 461 list.find_node(6), 462 Some(Located::Expression { 463 expression: list, 464 position: ExpressionPosition::Expression 465 }) 466 ); 467 assert_eq!( 468 list.find_node(7), 469 Some(Located::Expression { 470 expression: &int3, 471 position: ExpressionPosition::Expression 472 }) 473 ); 474 assert_eq!( 475 list.find_node(8), 476 Some(Located::Expression { 477 expression: &int3, 478 position: ExpressionPosition::Expression 479 }) 480 ); 481 assert_eq!( 482 list.find_node(9), 483 Some(Located::Expression { 484 expression: list, 485 position: ExpressionPosition::Expression 486 }) 487 ); 488} 489 490#[test] 491fn find_node_tuple() { 492 let statement = compile_expression(r#"#(1, 2, 3)"#); 493 let tuple = get_bare_expression(&statement); 494 495 let int1 = TypedExpr::Int { 496 location: SrcSpan { start: 2, end: 3 }, 497 type_: type_::int(), 498 value: "1".into(), 499 int_value: 1.into(), 500 }; 501 let int2 = TypedExpr::Int { 502 location: SrcSpan { start: 5, end: 6 }, 503 type_: type_::int(), 504 value: "2".into(), 505 int_value: 2.into(), 506 }; 507 let int3 = TypedExpr::Int { 508 location: SrcSpan { start: 8, end: 9 }, 509 type_: type_::int(), 510 value: "3".into(), 511 int_value: 3.into(), 512 }; 513 514 assert_eq!( 515 tuple.find_node(0), 516 Some(Located::Expression { 517 expression: tuple, 518 position: ExpressionPosition::Expression 519 }) 520 ); 521 assert_eq!( 522 tuple.find_node(1), 523 Some(Located::Expression { 524 expression: tuple, 525 position: ExpressionPosition::Expression 526 }) 527 ); 528 assert_eq!( 529 tuple.find_node(2), 530 Some(Located::Expression { 531 expression: &int1, 532 position: ExpressionPosition::Expression 533 }) 534 ); 535 assert_eq!( 536 tuple.find_node(3), 537 Some(Located::Expression { 538 expression: &int1, 539 position: ExpressionPosition::Expression 540 }) 541 ); 542 assert_eq!( 543 tuple.find_node(4), 544 Some(Located::Expression { 545 expression: tuple, 546 position: ExpressionPosition::Expression 547 }) 548 ); 549 assert_eq!( 550 tuple.find_node(5), 551 Some(Located::Expression { 552 expression: &int2, 553 position: ExpressionPosition::Expression 554 }) 555 ); 556 assert_eq!( 557 tuple.find_node(6), 558 Some(Located::Expression { 559 expression: &int2, 560 position: ExpressionPosition::Expression 561 }) 562 ); 563 assert_eq!( 564 tuple.find_node(7), 565 Some(Located::Expression { 566 expression: tuple, 567 position: ExpressionPosition::Expression 568 }) 569 ); 570 assert_eq!( 571 tuple.find_node(8), 572 Some(Located::Expression { 573 expression: &int3, 574 position: ExpressionPosition::Expression 575 }) 576 ); 577 assert_eq!( 578 tuple.find_node(9), 579 Some(Located::Expression { 580 expression: &int3, 581 position: ExpressionPosition::Expression 582 }) 583 ); 584 assert_eq!( 585 tuple.find_node(10), 586 Some(Located::Expression { 587 expression: tuple, 588 position: ExpressionPosition::Expression 589 }) 590 ); 591} 592 593#[test] 594fn find_node_binop() { 595 let statement = compile_expression(r#"1 + 2"#); 596 let expr = get_bare_expression(&statement); 597 assert!(expr.find_node(0).is_some()); 598 assert!(expr.find_node(1).is_some()); 599 assert!(expr.find_node(2).is_none()); 600 assert!(expr.find_node(3).is_none()); 601 assert!(expr.find_node(4).is_some()); 602 assert!(expr.find_node(5).is_some()); 603} 604 605#[test] 606fn find_node_tuple_index() { 607 let statement = compile_expression(r#"#(1).0"#); 608 let expr = get_bare_expression(&statement); 609 610 let int = TypedExpr::Int { 611 location: SrcSpan { start: 2, end: 3 }, 612 value: "1".into(), 613 int_value: 1.into(), 614 type_: type_::int(), 615 }; 616 617 assert_eq!( 618 expr.find_node(2), 619 Some(Located::Expression { 620 expression: &int, 621 position: ExpressionPosition::Expression 622 }) 623 ); 624 assert_eq!( 625 expr.find_node(5), 626 Some(Located::Expression { 627 expression: expr, 628 position: ExpressionPosition::Expression 629 }) 630 ); 631 assert_eq!( 632 expr.find_node(6), 633 Some(Located::Expression { 634 expression: expr, 635 position: ExpressionPosition::Expression 636 }) 637 ); 638} 639 640#[test] 641fn find_node_module_select() { 642 let expr = TypedExpr::ModuleSelect { 643 location: SrcSpan { start: 1, end: 4 }, 644 field_start: 2, 645 type_: type_::int(), 646 label: "label".into(), 647 module_name: "name".into(), 648 module_alias: "alias".into(), 649 constructor: ModuleValueConstructor::Fn { 650 module: "module".into(), 651 name: "function".into(), 652 external_erlang: None, 653 external_javascript: None, 654 location: SrcSpan { start: 1, end: 55 }, 655 documentation: None, 656 field_map: None, 657 purity: Purity::Pure, 658 }, 659 }; 660 661 assert_eq!(expr.find_node(0), None); 662 assert_eq!( 663 expr.find_node(1), 664 Some(Located::ModuleName { 665 location: SrcSpan::new(1, 1), 666 name: &"name".into(), 667 layer: super::Layer::Value 668 }) 669 ); 670 assert_eq!( 671 expr.find_node(2), 672 Some(Located::Expression { 673 expression: &expr, 674 position: ExpressionPosition::Expression 675 }) 676 ); 677 assert_eq!( 678 expr.find_node(3), 679 Some(Located::Expression { 680 expression: &expr, 681 position: ExpressionPosition::Expression 682 }) 683 ); 684} 685 686#[test] 687fn find_node_fn() { 688 let statement = compile_expression("fn() { 1 }"); 689 let expr = get_bare_expression(&statement); 690 691 let int = TypedExpr::Int { 692 location: SrcSpan { start: 7, end: 8 }, 693 value: "1".into(), 694 int_value: 1.into(), 695 type_: type_::int(), 696 }; 697 698 assert_eq!( 699 expr.find_node(0), 700 Some(Located::Expression { 701 expression: expr, 702 position: ExpressionPosition::Expression 703 }) 704 ); 705 assert_eq!( 706 expr.find_node(6), 707 Some(Located::Expression { 708 expression: expr, 709 position: ExpressionPosition::Expression 710 }) 711 ); 712 assert_eq!( 713 expr.find_node(7), 714 Some(Located::Expression { 715 expression: &int, 716 position: ExpressionPosition::Expression 717 }) 718 ); 719 assert_eq!( 720 expr.find_node(8), 721 Some(Located::Expression { 722 expression: &int, 723 position: ExpressionPosition::Expression 724 }) 725 ); 726 assert_eq!( 727 expr.find_node(9), 728 Some(Located::Expression { 729 expression: expr, 730 position: ExpressionPosition::Expression 731 }) 732 ); 733 assert_eq!( 734 expr.find_node(10), 735 Some(Located::Expression { 736 expression: expr, 737 position: ExpressionPosition::Expression 738 }) 739 ); 740} 741 742#[test] 743fn find_node_call() { 744 let statement = compile_expression("fn(_, _) { 1 }(1, 2)"); 745 let expr = get_bare_expression(&statement); 746 747 let return_ = TypedExpr::Int { 748 location: SrcSpan { start: 11, end: 12 }, 749 value: "1".into(), 750 int_value: 1.into(), 751 type_: type_::int(), 752 }; 753 754 let arg1 = TypedExpr::Int { 755 location: SrcSpan { start: 15, end: 16 }, 756 value: "1".into(), 757 int_value: 1.into(), 758 type_: type_::int(), 759 }; 760 761 let arg2 = TypedExpr::Int { 762 location: SrcSpan { start: 18, end: 19 }, 763 value: "2".into(), 764 int_value: 2.into(), 765 type_: type_::int(), 766 }; 767 768 let TypedExpr::Call { 769 fun: called_function, 770 arguments: function_arguments, 771 .. 772 } = expr 773 else { 774 panic!("Expression was not a function call"); 775 }; 776 777 assert_eq!( 778 expr.find_node(11), 779 Some(Located::Expression { 780 expression: &return_, 781 position: ExpressionPosition::Expression 782 }) 783 ); 784 assert_eq!( 785 expr.find_node(15), 786 Some(Located::Expression { 787 expression: &arg1, 788 position: ExpressionPosition::Expression 789 }) 790 ); 791 assert_eq!( 792 expr.find_node(16), 793 Some(Located::Expression { 794 expression: &arg1, 795 position: ExpressionPosition::ArgumentOrLabel { 796 called_function, 797 function_arguments 798 } 799 }) 800 ); 801 assert_eq!( 802 expr.find_node(17), 803 Some(Located::Expression { 804 expression: expr, 805 position: ExpressionPosition::Expression 806 }) 807 ); 808 assert_eq!( 809 expr.find_node(18), 810 Some(Located::Expression { 811 expression: &arg2, 812 position: ExpressionPosition::Expression 813 }) 814 ); 815 assert_eq!( 816 expr.find_node(19), 817 Some(Located::Expression { 818 expression: &arg2, 819 position: ExpressionPosition::ArgumentOrLabel { 820 called_function, 821 function_arguments 822 } 823 }) 824 ); 825 assert_eq!( 826 expr.find_node(20), 827 Some(Located::Expression { 828 expression: expr, 829 position: ExpressionPosition::Expression 830 }) 831 ); 832} 833 834#[test] 835fn find_node_record_access() { 836 let statement = compile_expression(r#"Cat("Nubi", 3).name"#); 837 let access = get_bare_expression(&statement); 838 839 let string = TypedExpr::String { 840 location: SrcSpan { start: 4, end: 10 }, 841 value: "Nubi".into(), 842 type_: type_::string(), 843 }; 844 845 let int = TypedExpr::Int { 846 location: SrcSpan { start: 12, end: 13 }, 847 value: "3".into(), 848 int_value: 3.into(), 849 type_: type_::int(), 850 }; 851 852 assert_eq!( 853 access.find_node(4), 854 Some(Located::Expression { 855 expression: &string, 856 position: ExpressionPosition::Expression 857 }) 858 ); 859 assert_eq!( 860 access.find_node(9), 861 Some(Located::Expression { 862 expression: &string, 863 position: ExpressionPosition::Expression 864 }) 865 ); 866 assert_eq!( 867 access.find_node(12), 868 Some(Located::Expression { 869 expression: &int, 870 position: ExpressionPosition::Expression 871 }) 872 ); 873 assert_eq!( 874 access.find_node(15), 875 Some(Located::Expression { 876 expression: access, 877 position: ExpressionPosition::Expression 878 }) 879 ); 880 assert_eq!( 881 access.find_node(18), 882 Some(Located::Expression { 883 expression: access, 884 position: ExpressionPosition::Expression 885 }) 886 ); 887 assert_eq!( 888 access.find_node(19), 889 Some(Located::Expression { 890 expression: access, 891 position: ExpressionPosition::Expression 892 }) 893 ); 894} 895 896#[test] 897fn find_node_record_update() { 898 let statement = compile_expression(r#"Cat(..Cat("Nubi", 3), age: 4)"#); 899 let update = get_bare_expression(&statement); 900 901 let cat = TypedExpr::Var { 902 location: SrcSpan { start: 0, end: 3 }, 903 constructor: ValueConstructor { 904 publicity: Publicity::Public, 905 deprecation: Deprecation::NotDeprecated, 906 variant: ValueConstructorVariant::Record { 907 name: "Cat".into(), 908 arity: 2, 909 field_map: Some(FieldMap { 910 arity: 2, 911 fields: [(EcoString::from("age"), 1), (EcoString::from("name"), 0)].into(), 912 }), 913 location: SrcSpan { start: 12, end: 15 }, 914 module: "mymod".into(), 915 variants_count: 1, 916 variant_index: 0, 917 documentation: Some("wibble".into()), 918 }, 919 type_: type_::fn_( 920 vec![type_::string(), type_::int()], 921 type_::named("mypackage", "mymod", "Cat", Publicity::Public, vec![]), 922 ), 923 }, 924 name: "Cat".into(), 925 }; 926 927 let int = TypedExpr::Int { 928 location: SrcSpan { start: 27, end: 28 }, 929 value: "4".into(), 930 int_value: 4.into(), 931 type_: type_::int(), 932 }; 933 934 assert_eq!( 935 update.find_node(0), 936 Some(Located::Expression { 937 expression: &cat, 938 position: ExpressionPosition::Expression 939 }) 940 ); 941 assert_eq!( 942 update.find_node(3), 943 Some(Located::Expression { 944 expression: &cat, 945 position: ExpressionPosition::Expression 946 }) 947 ); 948 assert_eq!( 949 update.find_node(27), 950 Some(Located::Expression { 951 expression: &int, 952 position: ExpressionPosition::Expression 953 }) 954 ); 955 assert_eq!( 956 update.find_node(28), 957 Some(Located::Expression { 958 expression: &int, 959 position: ExpressionPosition::Expression 960 }) 961 ); 962 assert_eq!( 963 update.find_node(29), 964 Some(Located::Expression { 965 expression: update, 966 position: ExpressionPosition::Expression 967 }) 968 ); 969} 970 971#[test] 972fn find_node_case() { 973 let statement = compile_expression( 974 r#" 975case 1, 2 { 976 _, _ -> 3 977} 978"#, 979 ); 980 let case = get_bare_expression(&statement); 981 982 let int1 = TypedExpr::Int { 983 location: SrcSpan { start: 6, end: 7 }, 984 value: "1".into(), 985 int_value: 1.into(), 986 type_: type_::int(), 987 }; 988 989 let int2 = TypedExpr::Int { 990 location: SrcSpan { start: 9, end: 10 }, 991 value: "2".into(), 992 int_value: 2.into(), 993 type_: type_::int(), 994 }; 995 996 let int3 = TypedExpr::Int { 997 location: SrcSpan { start: 23, end: 24 }, 998 value: "3".into(), 999 int_value: 3.into(), 1000 type_: type_::int(), 1001 }; 1002 1003 assert_eq!( 1004 case.find_node(1), 1005 Some(Located::Expression { 1006 expression: case, 1007 position: ExpressionPosition::Expression 1008 }) 1009 ); 1010 assert_eq!( 1011 case.find_node(6), 1012 Some(Located::Expression { 1013 expression: &int1, 1014 position: ExpressionPosition::Expression 1015 }) 1016 ); 1017 assert_eq!( 1018 case.find_node(9), 1019 Some(Located::Expression { 1020 expression: &int2, 1021 position: ExpressionPosition::Expression 1022 }) 1023 ); 1024 assert_eq!( 1025 case.find_node(23), 1026 Some(Located::Expression { 1027 expression: &int3, 1028 position: ExpressionPosition::Expression 1029 }) 1030 ); 1031 assert_eq!( 1032 case.find_node(25), 1033 Some(Located::Expression { 1034 expression: case, 1035 position: ExpressionPosition::Expression 1036 }) 1037 ); 1038 assert_eq!( 1039 case.find_node(26), 1040 Some(Located::Expression { 1041 expression: case, 1042 position: ExpressionPosition::Expression 1043 }) 1044 ); 1045 assert_eq!(case.find_node(27), None); 1046} 1047 1048#[test] 1049fn find_node_bool() { 1050 let statement = compile_expression(r#"!True"#); 1051 let negate = get_bare_expression(&statement); 1052 1053 let bool = TypedExpr::Var { 1054 location: SrcSpan { start: 1, end: 5 }, 1055 constructor: ValueConstructor { 1056 deprecation: Deprecation::NotDeprecated, 1057 publicity: Publicity::Public, 1058 variant: ValueConstructorVariant::Record { 1059 documentation: None, 1060 variants_count: 2, 1061 name: "True".into(), 1062 arity: 0, 1063 field_map: None, 1064 location: SrcSpan { start: 0, end: 0 }, 1065 module: PRELUDE_MODULE_NAME.into(), 1066 variant_index: 0, 1067 }, 1068 type_: type_::bool_with_variant(Some(true)), 1069 }, 1070 name: "True".into(), 1071 }; 1072 1073 assert_eq!( 1074 negate.find_node(0), 1075 Some(Located::Expression { 1076 expression: negate, 1077 position: ExpressionPosition::Expression 1078 }) 1079 ); 1080 assert_eq!( 1081 negate.find_node(1), 1082 Some(Located::Expression { 1083 expression: &bool, 1084 position: ExpressionPosition::Expression 1085 }) 1086 ); 1087 assert_eq!( 1088 negate.find_node(2), 1089 Some(Located::Expression { 1090 expression: &bool, 1091 position: ExpressionPosition::Expression 1092 }) 1093 ); 1094 assert_eq!( 1095 negate.find_node(3), 1096 Some(Located::Expression { 1097 expression: &bool, 1098 position: ExpressionPosition::Expression 1099 }) 1100 ); 1101 assert_eq!( 1102 negate.find_node(4), 1103 Some(Located::Expression { 1104 expression: &bool, 1105 position: ExpressionPosition::Expression 1106 }) 1107 ); 1108 assert_eq!( 1109 negate.find_node(5), 1110 Some(Located::Expression { 1111 expression: &bool, 1112 position: ExpressionPosition::Expression 1113 }) 1114 ); 1115} 1116 1117#[test] 1118fn find_node_statement_fn() { 1119 let module = compile_module( 1120 r#" 1121 1122pub fn main() { 1123 Nil 1124} 1125 1126"#, 1127 ); 1128 1129 assert!(module.find_node(0).is_none()); 1130 assert!(module.find_node(1).is_none()); 1131 1132 // The fn 1133 assert!(module.find_node(2).is_some()); 1134 assert!(module.find_node(24).is_some()); 1135 assert!(module.find_node(25).is_some()); 1136 assert!(module.find_node(26).is_none()); 1137} 1138 1139#[test] 1140fn find_node_statement_import() { 1141 let module = compile_module( 1142 r#" 1143import gleam 1144"#, 1145 ); 1146 1147 assert!(module.find_node(0).is_none()); 1148 1149 // The import 1150 assert!(module.find_node(1).is_some()); 1151 assert!(module.find_node(12).is_some()); 1152 assert!(module.find_node(13).is_some()); 1153 assert!(module.find_node(14).is_none()); 1154} 1155 1156#[test] 1157fn find_node_use() { 1158 let use_ = compile_expression( 1159 r#" 1160use x <- fn(f) { f(1) } 1161124 1162"#, 1163 ); 1164 1165 assert!(use_.find_node(0).is_none()); 1166 assert!(use_.find_node(1).is_some()); // The use 1167 assert!(use_.find_node(23).is_some()); 1168 assert!(use_.find_node(26).is_some()); // The int 1169}