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