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

Configure Feed

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

1// SPDX-License-Identifier: Apache-2.0 2// SPDX-FileCopyrightText: 2026 The Gleam contributors 3 4use ecow::EcoString; 5use itertools::Itertools; 6use num_bigint::BigInt; 7use num_traits::Zero; 8use regex::Regex; 9use std::sync::OnceLock; 10 11/// This is to raise an `unreachable` pretty printed error when we try producing 12/// some piece of code that is not allowed in the current position. 13macro_rules! invalid_code_for_position { 14 ($this:expr, $expected:literal) => { 15 unreachable!("{}", $this.error_with_position($expected)) 16 }; 17} 18 19/// This represent an erlang module name. 20/// Gleam modules use `/` as a separator, but when turned into erlang `@` is 21/// used as a separator instead. 22/// 23/// If we were to allow strings directly, a very common mistake to make would be 24/// to pass a Gleam module name to a function that's expecting an Erlang module 25/// name! 26/// 27/// With this those bugs cannot happen, and since this is a newtype wrapper its 28/// not adding any overhead over using plain strings. 29/// 30pub struct ErlangModuleName(EcoString); 31 32impl ErlangModuleName { 33 #[inline] 34 /// Creates a new erlang module name from a Gleam module name. 35 pub fn new(gleam_module_name: &str) -> Self { 36 Self(gleam_module_name.replace("/", "@").into()) 37 } 38 39 /// The Erlang/OTP `erlang` module. 40 pub fn erlang() -> Self { 41 Self("erlang".into()) 42 } 43 44 /// The Erlang/OTP `unicode` module. 45 pub fn unicode() -> Self { 46 Self("unicode".into()) 47 } 48} 49 50/// All the possible specifiers that can be used in a bit array segment. 51pub enum BitArraySegmentSpecifier { 52 Utf8, 53 Utf16, 54 Utf32, 55 Integer, 56 Float, 57 Binary, 58 Bitstring, 59 Signed, 60 Unsigned, 61 Little, 62 Big, 63 Native, 64 Unit(u8), 65} 66 67/// This represents what can go in a moduledoc or doc comment. Either the atom 68/// false, if the function/module is to be hidden from the public docs, or the 69/// string content to include. 70pub enum DocContent<'string> { 71 False, 72 String(&'string str), 73} 74 75/// A trait defining operations to describe the content of an Erlang module. 76/// 77/// This might look strange in places, for example why is there a `start_tuple` 78/// and `end_tuple` function, but lists are built using `cons_list` and not a 79/// `start_list` and `end_list` function? 80/// 81/// That's because this API has been made primarily to be able to generate 82/// the Erlang Abstract Format data structure. All the methods almost map 1:1 83/// to how Erlang constructs are represented in that format. 84/// 85/// You might want to keep a reference to it open as you go over this module, 86/// it's gonna be handy: 87/// https://www.erlang.org/doc/apps/erts/absform.html 88/// 89pub trait ErlangBuilder<Output> { 90 /// Represents an open function that has yet to be closed. 91 /// A function definition is started with `ErlangBuilder::start_function` and 92 /// _must_ be closed using `ErlangBuilder::end_function`. 93 type Function; 94 95 /// Represents an open function call that has yet to be closed. 96 type Call; 97 98 /// Represents an open function call where the called expression still has 99 /// to be generated. 100 type CalledExpression; 101 102 /// Represents an open case expression that has yet to be closed. 103 type Case; 104 105 /// Represents an open case subject that has yet to be closed. 106 type CaseSubject; 107 108 /// Represents an open case clause pattern that has yet to be generated. 109 type ClausePattern; 110 111 /// Represents a set of clause guards that has yet to be closed. 112 type ClauseGuards; 113 114 /// Represents a single clause guard that has yet to be closed. 115 type Guard; 116 117 /// Represents an open clause body that has yet to be closed. 118 type ClauseBody; 119 120 /// Represents an open tuple that has yet to be closed. 121 type Tuple; 122 123 /// Represents an open map that has yet to be closed. 124 type Map; 125 126 /// Represents an open bit array that has yet to be closed. 127 type BitArray; 128 129 /// Represents an open bit array pattern that has yet to be closed. 130 type BitArrayPattern; 131 132 /// Represents an open tuple type that has yet to be closed. 133 type TupleType; 134 135 /// Represents an open tuple pattern that has yet to be closed. 136 type TuplePattern; 137 138 /// Represents an open record attribute. 139 type RecordAttribute; 140 141 /// Represents an open function type annotation that has yet to be closed after 142 /// generating the arguments types and the return type. 143 type FunctionType; 144 145 /// Represents an open named type that has yet to be closed after generating 146 /// the types it takes as an argument (if any). 147 type NamedType; 148 149 /// Represents an open remote named type that has yet to be closed after 150 /// generating the types it takes as an argument (if any). 151 type RemoteNamedType; 152 153 /// Represents an open alternative type that has yet to be closed after 154 /// generating all of its alternatives. 155 type UnionType; 156 157 /// Represents an open function type annotation that has yet to be closed after 158 /// generating the arguments types and the return type. 159 type FunctionSpec; 160 161 /// Represents an open block that has yet to be closed after generating the 162 /// statements that go inside it. 163 type Block; 164 165 /// Represents an open list of arguments' types in a function type annotation 166 /// that has yet to be closed. 167 type FunctionTypeArguments; 168 169 /// Represents an open type spec attribute that has yet to be closed after 170 /// generating the type it stands for. 171 type TypeSpec; 172 173 /// Creates a new `ErlangBuilder` data structure to generate Erlang code. 174 /// If a module name is provided this will also automatically take care of 175 /// generating the appropriate `-module` annotation at the very beginning. 176 /// 177 /// It's optional because it might not always be needed. For example when 178 /// producing `-record` annotations there's no need to have a module name. 179 /// 180 fn new(module_name: Option<ErlangModuleName>) -> Self; 181 182 /// Consumes the given `ErlangBuilder` turning it into some other 183 /// representation. 184 /// For example that might be a binary representation, or a textual pretty 185 /// printed one. 186 /// 187 fn into_output(self) -> Output; 188 189 /// Adds to the module an export attribute for the given exported functions. 190 /// 191 /// For example: 192 /// 193 /// ```ignore 194 /// builder.export_attribute(vec![("wibble", 1), ("wobble", 2)]); 195 /// ``` 196 /// 197 /// Corresponds to: 198 /// 199 /// ```erl 200 /// -export([wibble/1, wobble/2]). 201 /// ``` 202 /// 203 fn export_attribute<Name: AsRef<str>>( 204 &mut self, 205 exported: impl IntoIterator<Item = (Name, usize)>, 206 ); 207 208 /// Adds to the module an export_type attribute for the given exported types. 209 /// 210 /// For example: 211 /// 212 /// ```ignore 213 /// builder.export_attribute(vec![("wibble", 1), ("wobble", 2)]); 214 /// ``` 215 /// 216 /// Corresponds to: 217 /// 218 /// ```erl 219 /// -export_type([wibble/1, wobble/2]). 220 /// ``` 221 /// 222 fn export_type_attribute<Name: AsRef<str>>( 223 &mut self, 224 exported: impl IntoIterator<Item = (Name, usize)>, 225 ); 226 227 /// Creates a `-doc` attribute with the given content. 228 /// For example: 229 /// 230 /// ```ignore 231 /// todo!() 232 /// ``` 233 /// 234 /// Corresponds to: 235 /// 236 /// ```erl 237 /// -doc(false). 238 /// ``` 239 /// 240 fn doc_attribute(&mut self, content: DocContent<'_>); 241 242 /// Creates a `-moduledoc` attribute with the given content. 243 /// For example: 244 /// 245 /// ```ignore 246 /// todo!() 247 /// ``` 248 /// 249 /// Corresponds to: 250 /// 251 /// ```erl 252 /// -moduledoc(false). 253 /// ``` 254 /// 255 fn moduledoc_attribute(&mut self, content: DocContent<'_>); 256 257 /// This generates the code for a `-compile([]).` attribute where all the 258 /// strings produces by the given iterator are going to be passed as atom 259 /// literals. 260 /// 261 /// For example: 262 /// 263 /// ```ignore 264 /// builder.compile_attribute(vec!["no_warn", "inline"]); 265 /// ``` 266 /// 267 /// Corresponds to: 268 /// 269 /// ```erl 270 /// -compile([no_warn, inline]). 271 /// ``` 272 /// 273 fn compile_attribute<'a>(&mut self, arguments: impl IntoIterator<Item = &'a str>); 274 275 /// This generates a `-file` attribute. 276 /// For example: 277 /// 278 /// ```ignore 279 /// builder.file_attribute("wibble.gleam", 2.into()); 280 /// ``` 281 /// 282 /// Correspods to: 283 /// 284 /// ```erl 285 /// -file("wibble.gleam", 2) 286 /// ``` 287 /// 288 fn file_attribute(&mut self, file: &str, line: u32); 289 290 /// Starts a `-record` attribute. 291 /// After this you're supposed to generate a sequence of `record_field`, and 292 /// once you're done you must end it with `end_record_attribute`. 293 /// 294 /// For example: 295 /// 296 /// ```ignore 297 /// let record = builder.start_record_attribute("wobble"); 298 /// builder.record_field(); 299 /// builder.atom("wibble"); 300 /// builder.literal_atom_type("ok"); 301 /// builder.close_record_attribute(record); 302 /// ``` 303 /// 304 /// Corresponds to: 305 /// 306 /// ```erl 307 /// -record(wobble, { wibble :: ok }). 308 /// ``` 309 /// 310 fn start_record_attribute(&mut self, record_name: &str) -> Self::RecordAttribute; 311 312 /// This closes the currently open record attribute. 313 /// Code generated after this is not gonna be part of it. 314 /// 315 fn end_record_attribute(&mut self, record: Self::RecordAttribute); 316 317 /// This creates a record field inside a record attribute. 318 /// After this you're supposed to generate two things: 319 /// - an atom representing the name of the field 320 /// - a type representing the type of the field 321 /// 322 /// For an example on how to use this you can check the 323 /// `start_record_attribute` docs. 324 fn record_field(&mut self); 325 326 /// This starts a function type spec. 327 /// Everything that is generated after this call is interpreted as the 328 /// annotated type of the function. So this must be followed by a single 329 /// function type. 330 /// 331 /// After that is complete, this has to be closed using `end_function_spec`. 332 /// 333 /// For example: 334 /// 335 /// ```ignore 336 /// let spec = builder.start_function_spec("wibble", 1) 337 /// let function_type = builder.start_function_type(); 338 /// builder.int_type(); 339 /// let function_type = builder.end_function_type_arguments(function_type); 340 /// builder.variable_type("A"); 341 /// builder.end_function_type(function_type); 342 /// ``` 343 /// 344 /// Corresponds to: 345 /// 346 /// ```erl 347 /// -spec wibble(integer(), A) -> A. 348 /// ``` 349 /// 350 fn start_function_spec(&mut self, name: &str, arity: usize) -> Self::FunctionSpec; 351 352 /// This closes the currently open function spec. 353 /// Code generated after this is not gonna be part of this function spec. 354 /// 355 fn end_function_spec(&mut self, function_spec: Self::FunctionSpec); 356 357 /// This starts an Erlang type spec. 358 /// After this call you're expected to generate a single type; that's going 359 /// to be the definition of the type. 360 /// After that is done you should call `end_type_spec`. 361 /// 362 /// For example: 363 /// 364 /// ```ignore 365 /// let spec = builder.start_type_spec(false, "wibble", ["A"]); 366 /// 367 /// let union = builder.start_union_type(); 368 /// builder.literal_atom_type("nil"); 369 /// 370 /// let list = builder.start_named_type("list"); 371 /// builder.type_variable("A") 372 /// builder.close_named_type(); 373 /// 374 /// builder.end_union_type(union); 375 /// builder.end_type_spec(spec); 376 /// ``` 377 /// 378 /// Corresponds to: 379 /// 380 /// ```erl 381 /// -spec wibble(A) :: nil | list(A). 382 /// ``` 383 /// 384 fn start_type_spec<Name: AsRef<str>>( 385 &mut self, 386 opaque: bool, 387 name: &str, 388 type_parameters: impl IntoIterator<Item = Name>, 389 ) -> Self::TypeSpec; 390 391 fn end_type_spec(&mut self, type_spec: Self::TypeSpec); 392 393 /// This starts a function type. 394 /// Any code generated after this is gonna be an argument type of the open 395 /// function type until `end_function_type_arguments` is called. 396 /// After that you must generate a single type that's gonna be the return 397 /// type, and then end the function. 398 /// 399 /// For example: 400 /// 401 /// ```ignore 402 /// let function_type = builder.start_function_type(); 403 /// builder.int_type(); 404 /// builder.variable_type("A"); 405 /// let function_type builder.end_function_type_arguments(function_type); 406 /// builder.variable_type("A"); 407 /// builder.end_function_type(function_type); 408 /// ``` 409 /// 410 /// Corresponds to: 411 /// 412 /// ```erl 413 /// (integer(), A) -> A. 414 /// ``` 415 /// 416 fn start_function_type(&mut self) -> Self::FunctionTypeArguments; 417 418 /// This closes the currently open function type arguments list. 419 /// This means that the next type that is generated is going to be the 420 /// return type of the open function type. 421 /// 422 /// After that you must call `end_function_type` to close the function 423 /// type. 424 /// 425 fn end_function_type_arguments( 426 &mut self, 427 function_type: Self::FunctionTypeArguments, 428 ) -> Self::FunctionType; 429 430 /// This takes a function type and closes it. 431 /// Code generated after this is not gonna be part of this function type. 432 /// 433 fn end_function_type(&mut self, function_type: Self::FunctionType); 434 435 /// This starts a named type (either defined previously in this module, or 436 /// a built-in Erlang type) with the given name. 437 /// Any code generated after this is gonna be an argument of the open 438 /// named type type until `end_named_type` is called. 439 /// 440 /// For example: 441 /// 442 /// ```ignore 443 /// let type_ = builder.start_named_type("wibble"); 444 /// builder.end_named_type(type_); 445 /// ``` 446 /// 447 /// Corresponds to: 448 /// 449 /// ```erl 450 /// wibble(). 451 /// ``` 452 /// 453 fn start_named_type(&mut self, name: &str) -> Self::NamedType; 454 455 /// This takes a named type and closes it. 456 /// Code generated after this is not gonna be part of this named type. 457 /// 458 fn end_named_type(&mut self, named_type: Self::NamedType); 459 460 /// This starts a remote named type with the given module and name. 461 /// Any code generated after this is gonna be an argument of the open 462 /// named type type until `end_named_type` is called. 463 /// 464 /// For example: 465 /// 466 /// ```ignore 467 /// let type_ = builder.start_remote_named_type("wibble", "wobble"); 468 /// builder.end_named_type(type_); 469 /// ``` 470 /// 471 /// Corresponds to: 472 /// 473 /// ```erl 474 /// wibble:wobble(). 475 /// ``` 476 /// 477 fn start_remote_named_type( 478 &mut self, 479 module: ErlangModuleName, 480 name: &str, 481 ) -> Self::RemoteNamedType; 482 483 /// This takes a remote named type and closes it. 484 /// Code generated after this is not gonna be part of this named type. 485 /// 486 fn end_remote_named_type(&mut self, named_type: Self::RemoteNamedType); 487 488 /// This starts a tuple type. 489 /// Any code generated after this is gonna be one of the tuple items. 490 /// 491 /// For example: 492 /// 493 /// ```ignore 494 /// let tuple = builder.start_tuple_type(); 495 /// builder.literal_atom_type("nil"); 496 /// builder.literal_atom_type("ok"); 497 /// builder.end_tuple_type(tuple); 498 /// ``` 499 /// 500 /// Corresponds to the following Erlang type: 501 /// 502 /// ```erl 503 /// {nil, ok}. 504 /// ``` 505 /// 506 fn start_tuple_type(&mut self) -> Self::TupleType; 507 508 /// This takes a tuple type and closes it. 509 /// Code generated after this is not gonna be part of this tuple type. 510 /// 511 fn end_tuple_type(&mut self, tuple: Self::TupleType); 512 513 /// This starts a union type. 514 /// Any code generated after this is gonna be a possible alternative of this 515 /// type. 516 /// 517 /// For example: 518 /// 519 /// ```ignore 520 /// let ok_or_error = builder.start_union_type(); 521 /// builder.literal_atom_type("ok"); 522 /// builder.literal_atom_type("error"); 523 /// builder.end_union_type(ok_or_error); 524 /// ``` 525 /// 526 /// Corresponds to: 527 /// 528 /// ```erl 529 /// ok | error. 530 /// ``` 531 /// 532 fn start_union_type(&mut self) -> Self::UnionType; 533 534 /// This takes a union type and closes it. 535 /// Code generated after this is not gonna be part of this union type. 536 /// 537 fn end_union_type(&mut self, union_type: Self::UnionType); 538 539 /// This generated the code for a type variable with the given name. 540 /// 541 /// For example, if we were to define the type of the identity function we 542 /// could do it like this: 543 /// 544 /// ```ignore 545 /// let function = builder.start_function_type(); 546 /// builder.type_variable("A"); 547 /// let function = builder.end_function_type_arguments(); 548 /// builder.type_variable("A"); 549 /// builder.end_function(function); 550 /// ``` 551 /// 552 /// And it corresponds to: 553 /// 554 /// ```erl 555 /// (A) -> A. 556 /// ``` 557 /// 558 fn type_variable(&mut self, name: &str); 559 560 /// This generated the code for a literal atom type (as opposed to the 561 /// type `atom()`). 562 /// 563 /// For example, the annotation of a function returning the atom `nil` 564 /// is be defined like this: 565 /// 566 /// ```ignore 567 /// let function = builder.start_function_type(); 568 /// let function = builder.end_function_type_arguments(); 569 /// builder.literal_atom_type("nil"); 570 /// builder.end_function(function); 571 /// ``` 572 /// 573 /// And it corresponds to: 574 /// 575 /// ```erl 576 /// % type of a function returning nil! 577 /// () -> nil. 578 /// ``` 579 /// 580 fn literal_atom_type(&mut self, name: &str); 581 582 /// This starts a module function definition. 583 /// Any code generated after this is gonna be a statement of the open 584 /// function until `end_function` is called. 585 /// 586 /// For example: 587 /// 588 /// ```ignore 589 /// let function = builder.start_function("first_name", 0, vec![]); 590 /// builder.string("Giacomo"); 591 /// builder.end_function(function); 592 /// ``` 593 /// 594 /// Corresponds to: 595 /// 596 /// ```erl 597 /// first_name() -> ~"Giacomo". 598 /// ``` 599 /// 600 fn start_function<Name: AsRef<str>>( 601 &mut self, 602 name: &str, 603 arity: usize, 604 arguments_names: impl IntoIterator<Item = Name>, 605 ) -> Self::Function; 606 607 /// This starts an expression defining an anonymous function. 608 /// Any code generated after this is gonna be a statement inside the 609 /// anonymous function's body until `end_anonymous_function` is called. 610 /// 611 /// For example: 612 /// 613 /// ```ignore 614 /// let function = builder.start_anonymous_function([]); 615 /// builder.string("Erlang rocks"); 616 /// builder.end_anonymous_function(function); 617 /// ``` 618 /// 619 /// Corresponds to: 620 /// 621 /// ```erl 622 /// fun() -> ~"Erlang rocks" end. 623 /// ``` 624 /// 625 fn start_anonymous_function<Name: AsRef<str>>( 626 &mut self, 627 arguments_names: impl IntoIterator<Item = Name>, 628 ) -> Self::Function; 629 630 /// This takes a function and closes it. 631 /// Code generated after this is not gonna be part of this function. 632 /// 633 fn end_function(&mut self, function: Self::Function); 634 635 /// This starts a block expression. 636 /// Any code generated after this is gonna be a statement inside the open 637 /// block. 638 /// 639 /// For example: 640 /// 641 /// ```ignore 642 /// let block = builder.start_block(); 643 /// builder.string("Giacomo"); 644 /// builder.int(1); 645 /// builder.end_block(block); 646 /// ``` 647 /// 648 /// Corresponds to: 649 /// 650 /// ```erl 651 /// begin 652 /// ~"Giacomo", 653 /// 1 654 /// end. 655 /// ``` 656 /// 657 fn start_block(&mut self) -> Self::Block; 658 659 /// This takes a block and closes it. 660 /// Code generated after this is not gonna be part of this block. 661 /// 662 fn end_block(&mut self, block: Self::Block); 663 664 /// This starts a remote call. 665 /// Any code generated after this is gonna be an argument of the open 666 /// function call `end_call` is called. 667 /// 668 /// For example: 669 /// 670 /// ```ignore 671 /// let call = builder.start_remote_call("io", "format"); 672 /// builder.string("Giacomo"); 673 /// builder.end_call(call); 674 /// ``` 675 /// 676 /// Corresponds to: 677 /// 678 /// ```erl 679 /// io:format(~"Giacomo"). 680 /// ``` 681 /// 682 fn start_remote_call(&mut self, module: ErlangModuleName, function: &str) -> Self::Call; 683 684 /// This starts a function call. 685 /// The expression generated immediately after this is going to be the thing 686 /// that is called, after generating it you must call the 687 /// `end_called_expression` function and generate its arguments. 688 /// 689 /// For example: 690 /// 691 /// ```ignore 692 /// let call = builder.start_call(); 693 /// builder.atom("wibble") 694 /// let call = builder.end_called_expression(call); 695 /// builder.string("Hello"); 696 /// builder.string("Giacomo"); 697 /// builder.end_call(call); 698 /// ``` 699 /// 700 /// Corresponds to: 701 /// 702 /// ```erl 703 /// wibble(~"Hello", ~"Giacomo"). 704 /// ``` 705 /// 706 fn start_call(&mut self) -> Self::CalledExpression; 707 708 /// This must be called after generating the expression that is called in a 709 /// function call. After that you can generate the arguments of the function 710 /// call. 711 fn end_called_expression(&mut self, called: Self::CalledExpression) -> Self::Call; 712 713 /// This takes an open call and closes it. 714 /// Code generated after this is not gonna be an argument to this call. 715 /// 716 fn end_call(&mut self, call: Self::Call); 717 718 /// This starts a tuple. 719 /// Any code generated after this is gonna be an item of the tuple. 720 /// 721 /// For example: 722 /// 723 /// ```ignore 724 /// let tuple = builder.start_tuple(); 725 /// builder.string("Hello"); 726 /// builder.int(1); 727 /// builder.end_tuple(tuple); 728 /// ``` 729 /// 730 /// Corresponds to: 731 /// 732 /// ```erl 733 /// {~"Hello", 1}. 734 /// ``` 735 /// 736 fn start_tuple(&mut self) -> Self::Tuple; 737 738 /// This takes an open tuple and closes it. 739 /// Code generated after this is not gonna be an item of the tuple. 740 /// 741 fn end_tuple(&mut self, tuple: Self::Tuple); 742 743 /// This starts an Erlang map. 744 /// After this call you can add fields to the map using the `map_field` 745 /// function. 746 /// 747 /// For example: 748 /// 749 /// ```ignore 750 /// let map = builder.start_map(); 751 /// 752 /// builder.map_field(); 753 /// builder.atom("gleam_error") 754 /// builder.atom("todo"); 755 /// 756 /// builder.map_field(); 757 /// builder.atom("line"); 758 /// builder.int(6.into()); 759 /// ``` 760 /// 761 /// Corresponds to: 762 /// 763 /// ```erl 764 /// #{ 765 /// gleam_error => todo, 766 /// line => 6 767 /// }. 768 /// ``` 769 /// 770 fn start_map(&mut self) -> Self::Map; 771 772 /// This takes an open map and closes it. 773 /// Code generated after this is not gonna be a map field. 774 /// 775 fn end_map(&mut self, map: Self::Map); 776 777 /// This is used to add new fields to an open map. 778 /// After calling this you must generate exactly two values: the first one 779 /// is going to be the key, while the second one is going to be the 780 /// associated value. 781 fn map_field(&mut self); 782 783 /// This starts an Erlang bitstring (that's a Gleam's BitArray). 784 /// Any code generated after this is gonna be a segment of the bitstring. 785 /// 786 /// For example: 787 /// 788 /// ```ignore 789 /// let bit_array = builder.start_bit_array(); 790 /// 791 /// builder.bit_array_segment(); 792 /// builder.int(1); 793 /// builder.bit_array_segment_default_size(); 794 /// builder.bit_array_segment_specifiers([]); 795 /// 796 /// builder.bit_array_segment(); 797 /// builder.string("hello"); 798 /// builder.bit_array_segment_default_size(); 799 /// builder.bit_array_segment_specifiers([]); 800 /// 801 /// builder.end_bit_array(bit_array); 802 /// ``` 803 /// 804 /// Corresponds to: 805 /// 806 /// ```erl 807 /// <<1, ~"hello">>. 808 /// ``` 809 /// 810 fn start_bit_array(&mut self) -> Self::BitArray; 811 812 /// This takes an open bit array and closes it. 813 /// Code generated after this is not gonna be a segment of the bit array. 814 /// 815 fn end_bit_array(&mut self, bit_array: Self::BitArray); 816 817 /// This starts a new bit array segment. Make sure to call it after 818 /// `start_bit_array`! 819 /// Bit array segments are a bit tricky, after calling this you're supposed 820 /// to generate three distinct bits in the following order: 821 /// 822 /// 1. The expression representing the bit array segment 823 /// 2. The expression representing the segment size (or the atom `default` 824 /// if you want to use... you guessed it, the default) 825 /// 3. A list of type specifiers (those are atoms like `utf8`, `binary`, 826 /// ...) or the atom `default` if you're ok with Erlang's default value, 827 /// those are generated using the `bit_array_segment_specifiers` function. 828 /// 829 /// After generating those three bits the segment is automatically over and 830 /// you can go on to the next one! 831 /// 832 /// If this API seems a bit tricky and easy to get wrong, it is! But this is 833 /// a low level API based on the shape of the Erlang Abstract Format itself, 834 /// we don't make the rules. 835 /// 836 /// If you wanna check an example of how this is used you can have a read at 837 /// the ones in `start_bit_array`. 838 fn bit_array_segment(&mut self); 839 840 /// You can call this when a bit array segment has no explicit size, and the 841 /// default Erlang behaviour is fine. 842 /// 843 fn bit_array_segment_default_size(&mut self); 844 845 /// This generates a specifiers list for the currently open bit array 846 /// segment. 847 /// You always have to call this function, even if the segment has no 848 /// specifiers; in that case you can pass this an empty list and the 849 /// Erlang's default will be applied. 850 /// 851 fn bit_array_segment_specifiers( 852 &mut self, 853 specifiers: impl IntoIterator<Item = BitArraySegmentSpecifier>, 854 ); 855 856 /// This creates a list. 857 /// The next two generated values are going to be respectively the first 858 /// item and the tail of the list. 859 /// 860 /// For example: 861 /// 862 /// ```ignore 863 /// builder.cons_list(); 864 /// builder.variable("Hello"); 865 /// builder.cons_list(); 866 /// builder.string("Giacomo"); 867 /// builder.empty_list(); 868 /// ``` 869 /// 870 /// Corresponds to: 871 /// 872 /// ```erl 873 /// [Hello | [ ~"Giacomo" | []]]. 874 /// ``` 875 /// 876 /// Which, with some syntax sugar, is how we represent a list with two 877 /// elements: 878 /// 879 /// ```erl 880 /// [Hello, ~"Giacomo"] 881 /// ``` 882 /// 883 fn cons_list(&mut self); 884 885 /// This creates an empty list. 886 /// 887 fn empty_list(&mut self); 888 889 /// This starts a new case expression. 890 /// After this function is called you're supposed to first generate a single 891 /// expression; that's going to be the case subject being matched on. 892 /// After that you must call `end_case_subject`. 893 /// 894 /// After that you're supposed to generate the case branches using the 895 /// `start_case_clause` function. 896 /// 897 /// For example: 898 /// 899 /// ```ignore 900 /// let case = builder.start_case(); 901 /// builder.variable("wibble"); 902 /// let case = builder.end_case_subject(); 903 /// 904 /// let clause = builder.start_case_clause(); 905 /// builder.discard_pattern(); 906 /// let clause = builder.end_clause_pattern(); 907 /// let clause = builder.end_clause_guards(); 908 /// builder.int(1.into()); 909 /// builder.end_clause_body(); 910 /// 911 /// builder.end_case(case); 912 /// ``` 913 /// 914 /// Corresponds to: 915 /// 916 /// ```erl 917 /// case Wibble of 918 /// _ -> 1 919 /// end. 920 /// ``` 921 /// 922 fn start_case(&mut self) -> Self::CaseSubject; 923 924 /// This ends the open case subject, after this you can start generating the 925 /// case clauses. 926 fn end_case_subject(&mut self, case: Self::CaseSubject) -> Self::Case; 927 928 /// This ends an open case expression. 929 /// Any code generated after this is not going to be part of it. 930 /// 931 fn end_case(&mut self, case: Self::Case); 932 933 /// This starts a new case clause inside a case expression. 934 /// After this is called you must generate a single pattern and then call 935 /// `end_clause_pattern`. 936 /// 937 /// For an example on how to generate a full case clause check the 938 /// `start_case` documentation. 939 fn start_case_clause(&mut self) -> Self::ClausePattern; 940 941 /// This ends the case clause's pattern. After this you must generate the 942 /// clause guards and then call `end_clause_guards`. 943 /// If the clause you're generating has no guards you can immediately call 944 /// that function without generating anything inbetween. 945 fn end_clause_pattern(&mut self, clause_pattern: Self::ClausePattern) -> Self::ClauseGuards; 946 947 /// You must call this before generating the guard of a case clause. 948 /// For example: 949 /// 950 /// ```ignore 951 /// let case = builder.start_case(); 952 /// builder.variable("wibble"); 953 /// let case = builder.end_case_subject(); 954 /// 955 /// let clause = builder.start_case_clause(); 956 /// builder.discard_pattern(); 957 /// let clause = builder.end_clause_pattern(); 958 /// let guard = builder.start_clause_guard(); 959 /// builder.atom("true"); 960 /// builder.builder.end_clause_guard(guard); 961 /// let clause = builder.end_clause_guards(); 962 /// builder.int(1.into()); 963 /// builder.end_clause_body(); 964 /// 965 /// builder.end_case(case); 966 /// ``` 967 /// 968 /// A clause might have multiple guards but, the way Gleam is compiled, you 969 /// should always call this function just once. A gleam guard is always 970 /// compiled as a single erlang guard with a single expression. 971 /// 972 fn start_clause_guard(&mut self) -> Self::Guard; 973 974 /// This ends an open clause guards. Anything that is generated after 975 /// this is going to be a new guard among the guards of a case's guards. 976 fn end_clause_guard(&mut self, clause_guard: Self::Guard); 977 978 /// This ends the case clause's guards. Anything that is generated after 979 /// this is going to be a statement inside the current case clause until 980 /// `end_clause_body` is called. 981 fn end_clause_guards(&mut self, clause_guards: Self::ClauseGuards) -> Self::ClauseBody; 982 983 /// This takes an open clause body and ends it. 984 /// After this you can start generating new case clauses, or end the 985 /// currently open case expression if this was the last clause! 986 fn end_clause_body(&mut self, clause_body: Self::ClauseBody); 987 988 /// This creates a variable expression with the given name. 989 /// For example: 990 /// 991 /// ```erl 992 /// wibble(X) -> X. 993 /// % ^ This here! 994 /// ``` 995 /// 996 fn variable(&mut self, name: &str); 997 998 /// This generated the code that is going to apply the given unary operator 999 /// to the expression that is going to be generated next. 1000 /// For example: 1001 /// 1002 /// ```ignore 1003 /// builder.unary_operator("-"); 1004 /// builder.variable("X"); 1005 /// ``` 1006 /// 1007 /// Corresponds to: 1008 /// 1009 /// ```erl 1010 /// -X. 1011 /// ``` 1012 /// 1013 fn unary_operator(&mut self, operator: &str); 1014 1015 /// This generated the code that is going to apply the given binary operator 1016 /// to the two expressions generated after it. 1017 /// For example: 1018 /// 1019 /// ```ignore 1020 /// builder.binary_operator("+"); 1021 /// builder.variable("X"); 1022 /// builder.int(1); 1023 /// ``` 1024 /// 1025 /// Corresponds to: 1026 /// 1027 /// ```erl 1028 /// X + 1. 1029 /// ``` 1030 /// 1031 fn binary_operator(&mut self, operator: &'static str); 1032 1033 /// This generates the code for a function reference. 1034 /// For example: 1035 /// 1036 /// ```ignore 1037 /// builder.function_reference(None, "wibble", 1); 1038 /// builder.function_reference(Some("io"), "format", 2); 1039 /// ``` 1040 /// 1041 /// Correspond to: 1042 /// 1043 /// ```erl 1044 /// fun wibble/1, 1045 /// fun io:format/2. 1046 /// ``` 1047 /// 1048 fn function_reference(&mut self, module: Option<ErlangModuleName>, name: &str, arity: usize); 1049 1050 /// This is used to create the code that corresponds to an assignment. 1051 /// A call to this function must always be followed by the generation of 1052 /// a pattern (the left-hand side of the assignment), and of an expression 1053 /// (the right-hand side of the assignment). 1054 /// 1055 /// For example: 1056 /// 1057 /// ```ignore 1058 /// builder.match_operator(); 1059 /// builder.variable_pattern("X"); 1060 /// builder.int(1); 1061 /// ``` 1062 /// 1063 /// Corresponds to: 1064 /// 1065 /// ```erl 1066 /// X = 1. 1067 /// ``` 1068 /// 1069 fn match_operator(&mut self); 1070 1071 /// This is used to create the code that corresponds to a match pattern. 1072 /// A call to this function must always be followed by the generation of 1073 /// a pattern (the left-hand side of the assignment), and of another pattern 1074 /// (the right-hand side of the assignment). 1075 /// 1076 /// For example: 1077 /// 1078 /// ```ignore 1079 /// builder.match_pattern(); 1080 /// builder.int_pattern(1); 1081 /// builder.variable_pattern("X"); 1082 /// ``` 1083 /// 1084 /// Corresponds to: 1085 /// 1086 /// ```erl 1087 /// 1 = X. 1088 /// ``` 1089 /// 1090 /// You could use this to compare equality of arbitrary complex patterns: 1091 /// `{1, A, [_, _]} = {X, Y, [A | _]}` however you'll most likely ever need 1092 /// this only when generating code for Gleam's "as" patterns where the right 1093 /// hand side is just a variable pattern. 1094 /// 1095 fn match_pattern(&mut self); 1096 1097 /// This creates a variable pattern with the given name. 1098 /// For example: 1099 /// 1100 /// ```erl 1101 /// wibble() -> 1102 /// X = 1. 1103 /// % ^ This here! 1104 /// ``` 1105 /// 1106 fn variable_pattern(&mut self, name: &str); 1107 1108 /// This creates a discard pattern. 1109 /// For example: 1110 /// 1111 /// ```erl 1112 /// wibble() -> 1113 /// _ = 1. 1114 /// % ^ This here! 1115 /// ``` 1116 /// 1117 fn discard_pattern(&mut self); 1118 1119 /// This creates an integer pattern. 1120 /// For example: 1121 /// 1122 /// ```erl 1123 /// wibble() -> 1124 /// 1 = X. 1125 /// % ^ This here! 1126 /// ``` 1127 /// 1128 fn int_pattern(&mut self, number: BigInt); 1129 1130 /// This creates an integer pattern. 1131 /// For example: 1132 /// 1133 /// ```erl 1134 /// wibble() -> 1135 /// 1 = X. 1136 /// % ^ This here! 1137 /// ``` 1138 /// 1139 fn float_pattern(&mut self, number: f64); 1140 1141 /// This creates a string pattern. 1142 /// For example: 1143 /// 1144 /// ```erl 1145 /// wibble() -> 1146 /// <<"Hello"/utf8>> = X. 1147 /// % ^^^^^^^^^^^^^^^^ This here! 1148 /// ``` 1149 /// 1150 fn string_pattern(&mut self, content: &str); 1151 1152 /// This creates an atom pattern. 1153 /// For example: 1154 /// 1155 /// ```erl 1156 /// wibble() -> 1157 /// ok = X. 1158 /// % ^^ This here! 1159 /// ``` 1160 /// 1161 fn atom_pattern(&mut self, name: &str); 1162 1163 /// This starts a tuple pattern. 1164 /// Any code generated after this is gonna be an item of the tuple pattern. 1165 /// 1166 /// For example: 1167 /// 1168 /// ```ignore 1169 /// let tuple = builder.start_tuple_pattern(); 1170 /// builder.int_pattern(1); 1171 /// builder.discard_pattern(); 1172 /// builder.end_tuple(tuple); 1173 /// ``` 1174 /// 1175 /// Corresponds to the following pattern: 1176 /// 1177 /// ```erl 1178 /// {~"Hello", _}. 1179 /// ``` 1180 /// 1181 fn start_tuple_pattern(&mut self) -> Self::TuplePattern; 1182 1183 /// This takes an open tuple pattern and closes it. 1184 /// Any code generated after this is not gonna be part of that pattern. 1185 fn end_tuple_pattern(&mut self, tuple: Self::TuplePattern); 1186 1187 /// This starts an Erlang bitstring (that's a Gleam's BitArray) pattern. 1188 /// Any code generated after this is gonna be a segment of the pattern. 1189 /// 1190 /// For example: 1191 /// 1192 /// ```ignore 1193 /// let bit_array = builder.start_bit_array_pattern(); 1194 /// 1195 /// builder.bit_array_pattern_segment(); 1196 /// builder.int_pattern(1); 1197 /// builder.bit_array_segment_default_size(); 1198 /// builder.bit_array_segment_specifiers([]); 1199 /// 1200 /// builder.bit_array_pattern_segment(); 1201 /// builder.discard_pattern(); 1202 /// builder.bit_array_segment_default_size(); 1203 /// builder.bit_array_segment_specifiers([]); 1204 /// 1205 /// builder.end_bit_array_pattern(bit_array); 1206 /// ``` 1207 /// 1208 /// Corresponds to the following pattern: 1209 /// 1210 /// ```erl 1211 /// <<1, _>>. 1212 /// ``` 1213 /// 1214 fn start_bit_array_pattern(&mut self) -> Self::BitArrayPattern; 1215 1216 /// This takes an open bit array pattern and closes it. 1217 /// Code generated after this is not gonna be a segment of the bit array. 1218 /// 1219 fn end_bit_array_pattern(&mut self, bit_array: Self::BitArrayPattern); 1220 1221 /// This creates a list pattern. 1222 /// The next two generated values are going to be respectively the pattern 1223 /// for the first item and the pattern for the tail of the list. 1224 /// 1225 /// For example: 1226 /// 1227 /// ```ignore 1228 /// builder.cons_list_pattern(); 1229 /// builder.discard_pattern(); 1230 /// builder.cons_list_pattern(); 1231 /// builder.string("Louis"); 1232 /// builder.empty_list_pattern(); 1233 /// ``` 1234 /// 1235 /// Corresponds to the following pattern: 1236 /// 1237 /// ```erl 1238 /// [_ | [ ~"Louis" | []]]. 1239 /// ``` 1240 /// 1241 /// Which, with some syntax sugar, is how we represent a pattern matching 1242 /// on a list with two elements, where the second element is the string 1243 /// `~"Louis"`: 1244 /// 1245 /// ```erl 1246 /// [_, ~"Louis"] 1247 /// ``` 1248 /// 1249 fn cons_list_pattern(&mut self); 1250 1251 /// This creates a pattern matching on the empty list. 1252 /// 1253 fn empty_list_pattern(&mut self); 1254 1255 /// This creates a string literal, where the string is represented as a 1256 /// bit array with the utf8 bytes making up the string. 1257 /// This is how Gleam string literals are represented in Erlang. 1258 /// 1259 /// For example: 1260 /// 1261 /// ```ignore 1262 /// builder.string("ksiąskę"); 1263 /// ``` 1264 /// 1265 /// Corresponds to: 1266 /// 1267 /// ```erl 1268 /// ~"ksiąskę". 1269 /// ``` 1270 /// 1271 /// Which is the same as `<<"ksiąskę"/utf8>>` 1272 /// Or the same as writing the bytes directly: 1273 /// 1274 /// ```erl 1275 /// <<107, 115, 105, 196, 133, 115, 107, 196, 153>> 1276 /// ``` 1277 /// 1278 fn string(&mut self, string: &str); 1279 1280 /// This creates an integer literal from the given value. 1281 /// 1282 /// For example: 1283 /// 1284 /// ```ignore 1285 /// builder.int(BigInt::from(2)) 1286 /// ``` 1287 /// 1288 /// Corresponds to: 1289 /// 1290 /// ```erl 1291 /// 2. 1292 /// ``` 1293 /// 1294 fn int(&mut self, value: BigInt); 1295 1296 /// This creates a float literal from the given value. 1297 /// 1298 /// For example: 1299 /// 1300 /// ```ignore 1301 /// builder.float(1.2) 1302 /// ``` 1303 /// 1304 /// Corresponds to: 1305 /// 1306 /// ```erl 1307 /// 1.2. 1308 /// ``` 1309 /// 1310 fn float(&mut self, value: f64); 1311 1312 /// This creates a literal atom with the given name. 1313 /// 1314 /// For example: 1315 /// 1316 /// ```ignore 1317 /// builder.atom("wibble") 1318 /// ``` 1319 /// 1320 /// Corresponds to: 1321 /// 1322 /// ```erl 1323 /// wibble. 1324 /// ``` 1325 /// 1326 fn atom(&mut self, name: &str); 1327} 1328 1329/// A structure that implements the `ErlangBuilder` trait and produces a nice 1330/// and readable Erlang source string. 1331#[derive(Debug)] 1332pub struct ErlangSourceBuilder { 1333 code: String, 1334 /// This keeps track of what we're generating 1335 position: Vec<ErlangSourceBuilderPosition>, 1336 /// The current indentation to use when generating stuff like case 1337 /// expressions, block statements, etc. 1338 indentation: usize, 1339} 1340 1341/// This is used to keep track of the current position when generating pretty 1342/// printed code from an `ErlangSourceBuilder`. 1343#[derive(Debug)] 1344enum ErlangSourceBuilderPosition { 1345 /// We're generating a function spec like `-spec wibble(atom()) -> atom()`. 1346 FunctionSpec, 1347 1348 /// We're generating code for a type spec like 1349 /// `-type wibble() :: {ok, integer()}`. 1350 TypeSpec { expected: TypeSpecExpectedItem }, 1351 1352 /// We're generating a function type, there's a couple of things that make 1353 /// it up that we will need to generate: its arguments and the return type. 1354 /// Which one we're expecting to see is described by the `expected` field. 1355 FunctionType { 1356 expected: ExpectedFunctionTypeItem, 1357 /// If a function type doesn't appear at the top level as a spec 1358 /// annotation, then we must wrap it in a `fun(...)`. For example: 1359 /// 1360 /// ```erl 1361 /// % in a spec annotation it simply comes after the function name: 1362 /// -spec wibble () -> integer(). 1363 /// wibble() -> 11. 1364 /// 1365 /// % but inside another type it has to be wrapped in `fun(...)`: 1366 /// -spec wobble () -> fun(() -> integer()) 1367 /// wobble() -> fun wibble/0. 1368 /// ``` 1369 /// 1370 /// This is `true` if the type has to be wrapped in `fun(...)` 1371 needs_wrapping: bool, 1372 }, 1373 1374 /// We're generating a named type like `integer()`, or `list(atom())`. 1375 NamedType { 1376 /// This is `true` is the first type argument of the named type has not 1377 /// been generated yet. 1378 first: bool, 1379 }, 1380 1381 /// We're generating a union type like `integer() | atom()`. 1382 UnionType { 1383 /// This is `true` is the first alternative of the union type has not 1384 /// been generated yet. 1385 first: bool, 1386 }, 1387 1388 /// We're generating a tuple type like `{integer(), atom()}`. 1389 TupleType { 1390 /// This is `true` is the first item of the tuple type has not been 1391 /// generated yet. 1392 first: bool, 1393 }, 1394 1395 /// We're generating the statements of a function. 1396 FunctionStatement { 1397 /// This is `true` if the first statement has not been generated yet. 1398 first: bool, 1399 }, 1400 1401 /// We're generating the statements of an anonymous function. 1402 AnonymousFunctionStatement { 1403 /// This is `true` if the first statement has not been generated yet. 1404 first: bool, 1405 }, 1406 1407 /// We're generating code for a match operator like `X = 1`. 1408 /// This is something that happens in multiple steps: first the pattern on 1409 /// the left hand side, second the expression on the right. 1410 MatchOperator { 1411 /// This keeps track of what we need to generate next. 1412 expected: ExpectedMatchSide, 1413 }, 1414 1415 /// We're generating code for a match pattern like `[1, A | _] = List`. 1416 /// This is something that happens in multiple steps: first the pattern on 1417 /// the left hand side, second the pattern on the right hand side. 1418 MatchPattern { 1419 /// This keeps track of what we need to generate next. 1420 expected: ExpectedMatchPatternSide, 1421 }, 1422 1423 /// We're generating a list. 1424 List { 1425 /// This is telling us if we're generating a list expression, or a list 1426 /// pattern. 1427 kind: ListKind, 1428 /// The list item we're expecting to see next. 1429 expected: ExpectedListItem, 1430 }, 1431 1432 /// We're generating code for a unary operator. We're waiting for the 1433 /// expression to apply the operator to. 1434 UnaryOperator, 1435 1436 /// We're generating a tuple. 1437 Tuple { 1438 /// This is `true` is the first tuple item has not been generated yet. 1439 first: bool, 1440 }, 1441 1442 /// We're generating a tuple pattern. 1443 TuplePattern { 1444 /// This is `true` if the first pattern of the tuple has not been 1445 /// generated ywt. 1446 first: bool, 1447 }, 1448 1449 /// We're generating the segments of a bit array. 1450 BitArray { 1451 /// Whether we're dealing with a bit array pattern, or a bit array 1452 /// expression. 1453 kind: BitArrayKind, 1454 1455 /// This is `true` if the first segment has not been generated yet. 1456 first: bool, 1457 }, 1458 1459 /// We're generating code for a segment of a bit array, like `10:1/signed`. 1460 BitArraySegment { 1461 expected: BitArraySegmentExpectedItem, 1462 /// This is `true` if the value of the bit array segment needs to be wrapped 1463 /// in parentheses. For example function calls need to be wrapped, or they 1464 /// would result in invalid Erlang being produced. 1465 /// 1466 /// ```erl 1467 /// <<x()/binary>> % This is a syntax error! 1468 /// <<(x())/binary>> % This is fine. 1469 /// ``` 1470 /// 1471 segment_value_needs_wrapping: bool, 1472 segment_size_needs_wrapping: bool, 1473 }, 1474 1475 /// We're generating a `begin ... end` block. 1476 Block { 1477 /// This is `true` is the first statement of the block has not been 1478 /// generated yet. 1479 first: bool, 1480 }, 1481 1482 /// We're generating code for a function call like `wibble(1, 2)`. 1483 /// This needs to happen in steps: first we generate the function being 1484 /// called (that could be any arbitrary expression after all), then we 1485 /// generate the arguments it's being called with. 1486 FunctionCall { 1487 expected: ExpectedCallItem, 1488 /// This is `true` if the thing that is being called needs to be wrapped 1489 /// in parentheses. This appears to be needed in just one case: if we 1490 /// are calling another function call expression. For example: 1491 /// 1492 /// ```erl 1493 /// wibble()() % this is invalid Erlang 1494 /// (wibble())() % this is valid Erlang 1495 /// ``` 1496 /// 1497 /// Actually this seems to be needed for OTP versions up to 28, in OTP 1498 /// 29 we can simply write `wibble()()`. However, since we have to 1499 /// support OTP 28 we will add the wrapping when needed. 1500 /// 1501 called_item_needs_wrapping: bool, 1502 }, 1503 1504 /// We're generating code for a binary operator like `1 + 3`. 1505 BinaryOperator { 1506 expected: ExpectedBinaryOperatorSide, 1507 /// Wether this binary operation needs to be wrapped in parentheses or 1508 /// not. 1509 needs_wrapping: bool, 1510 operator: &'static str, 1511 }, 1512 1513 /// We're generating code for a case expression. 1514 Case { expected: ExpectedCaseItem }, 1515 /// We're generating code for a case clause. 1516 CaseClause { expected: ExpectedCaseClauseItem }, 1517 /// We're generating the key-value pairs of a map. 1518 Map { 1519 /// This is `true` if no key-value pair has been generated yet. 1520 first: bool, 1521 }, 1522 /// We're generating a key-value pair inside a map. 1523 MapField { expected: MapFieldExpectedItem }, 1524 /// We're generating the fields of a record attribute. 1525 RecordAttribute { 1526 /// This is `true` if no field has been generated yet. 1527 first: bool, 1528 }, 1529 /// We're generating the field of a record attribute. That needs to happen 1530 /// in two steps: first we generate the name, second we generate the type of 1531 /// the field. 1532 RecordField { expected: ExpectedRecordFieldItem }, 1533 /// We're generating a guard in a possible series of guards in a clause. 1534 ClauseGuard, 1535} 1536 1537#[derive(Debug, Eq, PartialEq)] 1538enum ListKind { 1539 /// We're generating a list pattern. 1540 Pattern, 1541 /// We're generating a list expression. 1542 Expression, 1543} 1544 1545#[derive(Debug, Eq, PartialEq, Copy, Clone)] 1546enum BitArrayKind { 1547 /// We're generating a bit array pattern. 1548 Pattern, 1549 /// We're generating a bit array expression. 1550 Expression, 1551} 1552 1553/// A map field is made of two things: a key, and a value. It's not an item that 1554/// is closed explicitly with a `end_map_field` function. It is implicitly over 1555/// after two expressions are generated. So we need to keep track of what we're 1556/// expecting to be generated next. 1557#[derive(Debug)] 1558enum MapFieldExpectedItem { 1559 Key, 1560 Value, 1561} 1562 1563/// A record field is made of two things: a name, and a type. It's not an item 1564/// that is closed explicitly with a `end_record_field` function. 1565/// It is implicitly over after those two things are generated. 1566/// So we need to keep track of which we're expecting to be generated next. 1567#[derive(Debug)] 1568enum ExpectedRecordFieldItem { 1569 Name, 1570 Type, 1571} 1572 1573/// Generating a case clause is done in three separate steps: first we generate 1574/// a single pattern, then we have to generate the guards for the clause, 1575/// finally we will be generating the statements making up the clause's body. 1576/// 1577#[derive(Debug)] 1578enum ExpectedCaseClauseItem { 1579 Pattern, 1580 Guards { 1581 /// This is true if no guard has been generated yet. 1582 first: bool, 1583 }, 1584 Body { 1585 /// This is true if no body statement has been generated yet. 1586 first: bool, 1587 }, 1588} 1589 1590/// Generating a case expression is done in two steps: first we generate the 1591/// subject being matched on, then we generate the branches of the case 1592/// expression. 1593/// 1594#[derive(Debug)] 1595enum ExpectedCaseItem { 1596 /// We're waiting for the expression to be matched on to be generated. 1597 Subject, 1598 /// We've generated the expression to be matched on, and now are waiting for 1599 /// the case branches to be generated. 1600 Branches { 1601 /// This is `true` is no branch has been generated yet. 1602 first: bool, 1603 }, 1604} 1605 1606/// When generating a binary operator, that is made of three parts: the operator 1607/// and the left and right hand sides. 1608/// The way the Erlang Abstract Format works, we first generate the operator, 1609/// and then the two sides. 1610/// This is used to keep track which side we're expecting to see and properly 1611/// pretty print the output. 1612/// 1613#[derive(Debug)] 1614enum ExpectedBinaryOperatorSide { 1615 Left, 1616 Right, 1617 BinaryOperatorIsOver, 1618} 1619 1620/// When generating a bit array segment we need to generate exactly three 1621/// things: the value, the size, and the type specifiers. 1622/// This keeps track of which one we're expecting to be generated next. 1623/// 1624#[derive(Debug)] 1625enum BitArraySegmentExpectedItem { 1626 Value { 1627 /// This is telling us if the value of the segment has to be a pattern 1628 /// or an expression. 1629 kind: BitArrayKind, 1630 }, 1631 Size, 1632 Specifiers, 1633} 1634 1635/// When generating a function call, that is made of two parts: the function to 1636/// be called (that could be a simple literal atom, denoting a function from the 1637/// current module, or any expression), and its arguments. 1638/// 1639#[derive(Debug)] 1640enum ExpectedCallItem { 1641 /// We're waiting for the function to be called to be generated 1642 FunctionToBeCalled, 1643 /// The function to be called was generated, now we're waiting for its 1644 /// arguments. 1645 Arguments { first: bool }, 1646} 1647 1648/// When generating a function type, that is made of two parts: the type 1649/// arguments of the function, and the return type. 1650/// 1651#[derive(Debug)] 1652enum ExpectedFunctionTypeItem { 1653 Arguments { first: bool }, 1654 ReturnType, 1655} 1656 1657/// Type specs don't have a "end_" function. They are implicitly over once a 1658/// type is generated. This is used to keep track of what we're expecting to 1659/// see. 1660/// 1661#[derive(Debug)] 1662enum TypeSpecExpectedItem { 1663 TypeDefinition, 1664 TypeSpecIsOver, 1665} 1666 1667/// A match operator is made of two sides: `X = 1`. A pattern and an expression. 1668/// 1669#[derive(Debug)] 1670enum ExpectedMatchSide { 1671 /// We're waiting for the pattern on the left hand side of an assignment to 1672 /// be generated. 1673 Pattern, 1674 /// We're waiting for the expression on the right hand side of an assignment 1675 /// to be generated. 1676 Expression, 1677} 1678 1679/// An as pattern is made of two sides: `[1, _ | _] = List`. 1680/// A pattern and a variable pattern for the name. 1681/// 1682#[derive(Debug)] 1683enum ExpectedMatchPatternSide { 1684 /// We're waiting for the pattern on the left hand side of the match pattern 1685 /// to be generated. 1686 Left, 1687 /// We're waiting for the pattern on the right hand side of the match 1688 /// pattern to be generated. 1689 Right, 1690} 1691 1692/// Lists are built by cons cells, so when building a list we will do something 1693/// like this: `[a | [b | []]]`. 1694/// This is telling us if we're expecting the first item, the second list, or if 1695/// the list is actually over. 1696/// 1697#[derive(Debug)] 1698enum ExpectedListItem { 1699 First, 1700 Rest, 1701 ListIsOver, 1702} 1703 1704static UNICODE_ESCAPE_SEQUENCE_PATTERN: OnceLock<Regex> = OnceLock::new(); 1705 1706/// How does pretty printing work? Here's a high level overview of how it works: 1707/// 1708/// - When a new element is generated we call the `new_x` method. 1709/// If I'm generating an integer (or any expression) I call `new_expression`; 1710/// if I'm generating a pattern I call `new_pattern`. 1711/// - The `new_x` functions make sure that we're allowed to generate that 1712/// element in the current context (for example if I'm generating a tuple type 1713/// I can't start generating expression)! 1714/// - The `new_x` functions also make sure to add any code that is needed before 1715/// this new expression we're about to generate given the current context. 1716/// For example, say we're generating the items of a tuple, and we add another 1717/// one: first the call to `new_expression` is going to make sure to add 1718/// a comma to separate the previous item from the new one. 1719/// 1720/// - Then we can start pushing the code needed to generate whatever it is we 1721/// are generating. If it's something simple like an integer we can just push 1722/// its string representation. 1723/// - There's also plenty of elements that are not "self-closing" and will be 1724/// generated in multiple steps (like function calls, tuples with multiple 1725/// items, binary operators, ...). In that case we can push a new `position` 1726/// to update the current context and keep track of what we're doing! 1727/// - Whenever we reach a `end_x` function we can pop the position we pushed on 1728/// the stack. That's the moment we can add whatever is needed to "close" one 1729/// of those complex elements. For example if I'm done generating a function's 1730/// body I can add a full stop at the end of it; if I'm done generating a 1731/// tuple I can add the final `}` after all the elements, and so on... 1732/// 1733/// - There's one final tricky bit. Not all elements that are generated in 1734/// multiple steps have a `end_x` function (for example binary operators and 1735/// assignments). Those will end after a specific sequence of elements is 1736/// generated. 1737/// For example, if I call `self.match_operator` I know that it will be over 1738/// after the next pattern and expression are generated: 1739/// 1740/// ```ignore 1741/// // X = 1 1742/// builder.match_operator() 1743/// builder.variable_pattern("X") 1744/// builder.int(1) 1745/// ``` 1746/// 1747/// Notice how here we don't have a `start_match_operator` and 1748/// `end_match_operator`. As you'll see in the implementation these will 1749/// require a bit of extra book-keeping in the `new_x` functions. 1750/// 1751impl ErlangBuilder<String> for ErlangSourceBuilder { 1752 type BitArray = (); 1753 type BitArrayPattern = (); 1754 type Block = (); 1755 type CalledExpression = (); 1756 type Call = (); 1757 type Case = (); 1758 type Guard = (); 1759 type CaseSubject = (); 1760 type ClauseBody = (); 1761 type ClauseGuards = (); 1762 type ClausePattern = (); 1763 type Function = (); 1764 type FunctionSpec = (); 1765 type FunctionType = (); 1766 type FunctionTypeArguments = (); 1767 type Map = (); 1768 type NamedType = (); 1769 type RemoteNamedType = (); 1770 type RecordAttribute = (); 1771 type Tuple = (); 1772 type TuplePattern = (); 1773 type TupleType = (); 1774 type UnionType = (); 1775 type TypeSpec = (); 1776 1777 fn new(module: Option<ErlangModuleName>) -> Self { 1778 Self { 1779 code: if let Some(module) = module { 1780 format!("-module({}).\n", quote_atom_name(&module.0)) 1781 } else { 1782 String::new() 1783 }, 1784 indentation: 0, 1785 position: vec![], 1786 } 1787 } 1788 1789 fn into_output(mut self) -> String { 1790 self.close_currently_open_item(); 1791 self.code.push('\n'); 1792 self.code 1793 } 1794 1795 fn export_attribute<'a, Name: AsRef<str>>( 1796 &mut self, 1797 exported: impl IntoIterator<Item = (Name, usize)>, 1798 ) { 1799 // If there's no item in the iterator we don't add the attribute at all. 1800 let mut exported = exported.into_iter().peekable(); 1801 if exported.peek().is_none() { 1802 return; 1803 } 1804 1805 self.new_top_level_form(); 1806 1807 self.code.push_str("-export(["); 1808 let mut first = true; 1809 for (name, arity) in exported { 1810 if first { 1811 first = false; 1812 } else { 1813 self.code.push_str(", "); 1814 } 1815 1816 self.code.push_str(&quote_atom_name(name.as_ref())); 1817 self.code.push('/'); 1818 self.code.push_str(&arity.to_string()) 1819 } 1820 self.code.push_str("]).\n"); 1821 } 1822 1823 fn export_type_attribute<'a, Name: AsRef<str>>( 1824 &mut self, 1825 exported: impl IntoIterator<Item = (Name, usize)>, 1826 ) { 1827 // If there's no item in the iterator we don't add the attribute at all. 1828 let mut exported = exported.into_iter().peekable(); 1829 if exported.peek().is_none() { 1830 return; 1831 } 1832 1833 self.new_top_level_form(); 1834 1835 self.code.push_str("-export_type(["); 1836 let mut first = true; 1837 for (name, arity) in exported { 1838 if first { 1839 first = false; 1840 } else { 1841 self.code.push_str(", "); 1842 } 1843 1844 self.code.push_str(&quote_atom_name(name.as_ref())); 1845 self.code.push('/'); 1846 self.code.push_str(&arity.to_string()) 1847 } 1848 self.code.push_str("]).\n"); 1849 } 1850 1851 fn doc_attribute(&mut self, content: DocContent<'_>) { 1852 self.new_top_level_form(); 1853 self.code.push_str("-doc("); 1854 self.doc_content(content); 1855 self.code.push_str(").\n") 1856 } 1857 1858 fn moduledoc_attribute(&mut self, content: DocContent<'_>) { 1859 self.new_top_level_form(); 1860 self.code.push_str("-moduledoc("); 1861 self.doc_content(content); 1862 self.code.push_str(").\n") 1863 } 1864 1865 fn compile_attribute<'a>(&mut self, arguments: impl IntoIterator<Item = &'a str>) { 1866 self.new_top_level_form(); 1867 1868 self.code.push_str("-compile(["); 1869 1870 let mut first = true; 1871 for argument in arguments { 1872 if first { 1873 first = false; 1874 } else { 1875 self.code.push_str(", "); 1876 } 1877 1878 self.code.push_str(argument); 1879 } 1880 self.code.push_str("]).\n"); 1881 } 1882 1883 fn file_attribute(&mut self, file: &str, line: u32) { 1884 self.new_top_level_form(); 1885 self.code.push_str("\n-file(\""); 1886 self.code.push_str(file); 1887 self.code.push_str("\", "); 1888 self.code.push_str(&line.to_string()); 1889 self.code.push_str(")."); 1890 } 1891 1892 fn start_record_attribute(&mut self, record_name: &str) -> Self::RecordAttribute { 1893 self.new_top_level_form(); 1894 self.code.push_str("-record("); 1895 self.code.push_str(&quote_atom_name(record_name)); 1896 self.code.push_str(", {"); 1897 self.indentation += INDENT; 1898 self.position 1899 .push(ErlangSourceBuilderPosition::RecordAttribute { first: true }); 1900 } 1901 1902 fn end_record_attribute(&mut self, _record: Self::RecordAttribute) { 1903 self.close_currently_open_item(); 1904 } 1905 1906 fn record_field(&mut self) { 1907 self.new_record_field(); 1908 self.position 1909 .push(ErlangSourceBuilderPosition::RecordField { 1910 expected: ExpectedRecordFieldItem::Name, 1911 }); 1912 } 1913 1914 fn start_function_spec(&mut self, name: &str, _arity: usize) -> Self::FunctionSpec { 1915 self.new_top_level_form(); 1916 self.code.push_str("\n-spec "); 1917 self.code.push_str(&quote_atom_name(name)); 1918 self.position 1919 .push(ErlangSourceBuilderPosition::FunctionSpec); 1920 } 1921 1922 fn end_function_spec(&mut self, _function_spec: Self::FunctionSpec) { 1923 self.close_currently_open_item(); 1924 } 1925 1926 fn start_type_spec<Name: AsRef<str>>( 1927 &mut self, 1928 opaque: bool, 1929 name: &str, 1930 type_variables: impl IntoIterator<Item = Name>, 1931 ) -> Self::TypeSpec { 1932 self.new_top_level_form(); 1933 self.code.push('\n'); 1934 self.code 1935 .push_str(if opaque { "-opaque " } else { "-type " }); 1936 self.code.push_str(&quote_atom_name(name)); 1937 self.code.push('('); 1938 1939 let mut first = true; 1940 for type_variable in type_variables { 1941 if first { 1942 first = false 1943 } else { 1944 self.code.push_str(", ") 1945 } 1946 self.code.push_str(type_variable.as_ref()) 1947 } 1948 self.code.push_str(") :: "); 1949 self.position.push(ErlangSourceBuilderPosition::TypeSpec { 1950 expected: TypeSpecExpectedItem::TypeDefinition, 1951 }); 1952 } 1953 1954 fn end_type_spec(&mut self, _type_spec: Self::TypeSpec) { 1955 // For the pretty printer type specs do not need any extra book keeping. 1956 // Ending one does nothing because the spec is already over and doesn't 1957 // change the builder's position. 1958 } 1959 1960 fn start_function_type(&mut self) -> Self::FunctionTypeArguments { 1961 self.new_type(); 1962 1963 let needs_wrapping = 1964 if let Some(ErlangSourceBuilderPosition::FunctionSpec) = self.position.last() { 1965 self.code.push('('); 1966 false 1967 } else { 1968 self.code.push_str("fun(("); 1969 true 1970 }; 1971 1972 self.position 1973 .push(ErlangSourceBuilderPosition::FunctionType { 1974 expected: ExpectedFunctionTypeItem::Arguments { first: true }, 1975 needs_wrapping, 1976 }); 1977 } 1978 1979 fn end_function_type_arguments( 1980 &mut self, 1981 _function_type: Self::FunctionTypeArguments, 1982 ) -> Self::FunctionType { 1983 self.close_currently_open_item(); 1984 } 1985 1986 fn end_function_type(&mut self, _function_type: Self::FunctionType) { 1987 self.close_currently_open_item(); 1988 } 1989 1990 fn start_named_type(&mut self, name: &str) -> Self::NamedType { 1991 self.new_type(); 1992 self.position 1993 .push(ErlangSourceBuilderPosition::NamedType { first: true }); 1994 self.code.push_str(&quote_atom_name(name)); 1995 self.code.push('('); 1996 } 1997 1998 fn end_named_type(&mut self, _named_type: Self::NamedType) { 1999 self.close_currently_open_item(); 2000 } 2001 2002 fn start_remote_named_type(&mut self, module: ErlangModuleName, name: &str) -> Self::NamedType { 2003 self.new_type(); 2004 self.position 2005 .push(ErlangSourceBuilderPosition::NamedType { first: true }); 2006 self.code.push_str(&quote_atom_name(&module.0)); 2007 self.code.push(':'); 2008 self.code.push_str(&quote_atom_name(name)); 2009 self.code.push('('); 2010 } 2011 2012 fn end_remote_named_type(&mut self, _named_type: Self::RemoteNamedType) { 2013 self.close_currently_open_item(); 2014 } 2015 2016 fn start_tuple_type(&mut self) -> Self::TupleType { 2017 self.new_type(); 2018 self.position 2019 .push(ErlangSourceBuilderPosition::TupleType { first: true }); 2020 self.code.push('{'); 2021 } 2022 2023 fn end_tuple_type(&mut self, _tuple: Self::TupleType) { 2024 self.close_currently_open_item(); 2025 } 2026 2027 fn start_union_type(&mut self) -> Self::UnionType { 2028 self.new_type(); 2029 self.position 2030 .push(ErlangSourceBuilderPosition::UnionType { first: true }); 2031 } 2032 2033 fn end_union_type(&mut self, _union_type: Self::UnionType) { 2034 self.close_currently_open_item(); 2035 } 2036 2037 fn type_variable(&mut self, name: &str) { 2038 self.new_type(); 2039 self.code.push_str(name); 2040 } 2041 2042 fn literal_atom_type(&mut self, name: &str) { 2043 self.new_type(); 2044 self.code.push_str(&quote_atom_name(name)); 2045 } 2046 2047 fn start_function<Name: AsRef<str>>( 2048 &mut self, 2049 name: &str, 2050 _arity: usize, 2051 arguments_names: impl IntoIterator<Item = Name>, 2052 ) -> Self::Function { 2053 self.new_top_level_form(); 2054 self.code.push_str(&quote_atom_name(name)); 2055 self.code.push('('); 2056 2057 let mut first = true; 2058 for argument in arguments_names { 2059 if !first { 2060 self.code.push_str(", ") 2061 } else { 2062 first = false; 2063 } 2064 self.code.push_str(argument.as_ref()) 2065 } 2066 2067 self.code.push_str(") ->"); 2068 self.indentation += INDENT; 2069 self.position 2070 .push(ErlangSourceBuilderPosition::FunctionStatement { first: true }); 2071 } 2072 2073 fn start_anonymous_function<Name: AsRef<str>>( 2074 &mut self, 2075 arguments_names: impl IntoIterator<Item = Name>, 2076 ) -> Self::Function { 2077 self.new_expression(); 2078 self.code.push_str("fun("); 2079 2080 let mut first = true; 2081 for argument in arguments_names { 2082 if !first { 2083 self.code.push_str(", ") 2084 } else { 2085 first = false; 2086 } 2087 self.code.push_str(argument.as_ref()) 2088 } 2089 2090 self.code.push_str(") ->"); 2091 self.indentation += INDENT; 2092 self.position 2093 .push(ErlangSourceBuilderPosition::AnonymousFunctionStatement { first: true }); 2094 } 2095 2096 fn end_function(&mut self, _function: Self::Function) { 2097 self.close_currently_open_item(); 2098 } 2099 2100 fn start_block(&mut self) -> Self::Block { 2101 self.new_expression(); 2102 self.code.push_str("begin"); 2103 self.indentation += INDENT; 2104 self.position 2105 .push(ErlangSourceBuilderPosition::Block { first: true }); 2106 } 2107 2108 fn end_block(&mut self, _block: Self::Block) { 2109 self.close_currently_open_item(); 2110 } 2111 2112 fn start_remote_call(&mut self, module: ErlangModuleName, function: &str) -> Self::Call { 2113 self.pop_leftover_items(); 2114 2115 // If this function call we're generating is itself being called then 2116 // it is going to need to be wrapped in parentheses to be valid in 2117 // OTP 28: it is not ok to write `wibble()()`, but we have to write 2118 // `(wibble())()`. 2119 if let Some(ErlangSourceBuilderPosition::FunctionCall { 2120 expected: ExpectedCallItem::FunctionToBeCalled, 2121 called_item_needs_wrapping, 2122 }) = self.position.last_mut() 2123 { 2124 *called_item_needs_wrapping = true; 2125 }; 2126 2127 self.new_expression(); 2128 self.code.push_str(&quote_atom_name(&module.0)); 2129 self.code.push(':'); 2130 self.code.push_str(&quote_atom_name(function)); 2131 self.position 2132 .push(ErlangSourceBuilderPosition::FunctionCall { 2133 expected: ExpectedCallItem::Arguments { first: true }, 2134 called_item_needs_wrapping: false, 2135 }); 2136 } 2137 2138 fn start_call(&mut self) -> Self::Call { 2139 self.pop_leftover_items(); 2140 2141 // If this function call we're generating is itself being called then 2142 // it is going to need to be wrapped in parentheses to be valid in 2143 // OTP 28: it is not ok to write `wibble()()`, but we have to write 2144 // `(wibble())()`. 2145 if let Some(ErlangSourceBuilderPosition::FunctionCall { 2146 expected: ExpectedCallItem::FunctionToBeCalled, 2147 called_item_needs_wrapping, 2148 }) = self.position.last_mut() 2149 { 2150 *called_item_needs_wrapping = true; 2151 }; 2152 2153 self.new_expression(); 2154 self.position 2155 .push(ErlangSourceBuilderPosition::FunctionCall { 2156 expected: ExpectedCallItem::FunctionToBeCalled, 2157 called_item_needs_wrapping: false, 2158 }); 2159 } 2160 2161 fn end_called_expression(&mut self, _called: Self::CalledExpression) -> Self::Call { 2162 // We need to make sure that just a single expression was generated as 2163 // the called expression. 2164 // So we can assert that we're no longer expecting the called expression 2165 // but the arguments, and none has been generated yet. 2166 self.pop_leftover_items(); 2167 let Some(ErlangSourceBuilderPosition::FunctionCall { 2168 expected: ExpectedCallItem::Arguments { first: true }, 2169 .. 2170 }) = self.position.last() 2171 else { 2172 invalid_code_for_position!(self, "end called expression") 2173 }; 2174 } 2175 2176 fn end_call(&mut self, _call: Self::Call) { 2177 self.close_currently_open_item(); 2178 } 2179 2180 fn start_tuple(&mut self) -> Self::Tuple { 2181 self.new_expression(); 2182 self.code.push('{'); 2183 self.position 2184 .push(ErlangSourceBuilderPosition::Tuple { first: true }); 2185 } 2186 2187 fn end_tuple(&mut self, _tuple: Self::Tuple) { 2188 self.close_currently_open_item(); 2189 } 2190 2191 fn start_map(&mut self) -> Self::Map { 2192 self.new_expression(); 2193 self.code.push_str("#{"); 2194 self.indentation += INDENT; 2195 self.position 2196 .push(ErlangSourceBuilderPosition::Map { first: true }); 2197 } 2198 2199 fn end_map(&mut self, _map: Self::Map) { 2200 self.close_currently_open_item(); 2201 } 2202 2203 fn map_field(&mut self) { 2204 self.new_map_field(); 2205 self.position.push(ErlangSourceBuilderPosition::MapField { 2206 expected: MapFieldExpectedItem::Key, 2207 }); 2208 } 2209 2210 fn start_bit_array(&mut self) -> Self::BitArray { 2211 self.do_not_wrap_if_segment_value_or_size(); 2212 self.new_expression(); 2213 self.code.push_str("<<"); 2214 self.position.push(ErlangSourceBuilderPosition::BitArray { 2215 kind: BitArrayKind::Expression, 2216 first: true, 2217 }); 2218 } 2219 2220 fn end_bit_array(&mut self, _bit_array: Self::BitArray) { 2221 self.close_currently_open_item(); 2222 } 2223 2224 fn bit_array_segment(&mut self) { 2225 let kind = self.new_bit_array_segment(); 2226 self.position 2227 .push(ErlangSourceBuilderPosition::BitArraySegment { 2228 expected: BitArraySegmentExpectedItem::Value { kind }, 2229 // We assume all values are going to have to be wrapped, better 2230 // be safe than sorry! 2231 // We will turn this off only for certain expressions we know 2232 // are safe to not wrap, like bare integers and strings. 2233 segment_value_needs_wrapping: true, 2234 segment_size_needs_wrapping: true, 2235 }) 2236 } 2237 2238 fn bit_array_segment_default_size(&mut self) { 2239 self.pop_leftover_items(); 2240 2241 if let Some(ErlangSourceBuilderPosition::BitArraySegment { 2242 expected: expected @ BitArraySegmentExpectedItem::Size, 2243 segment_value_needs_wrapping, 2244 segment_size_needs_wrapping, 2245 }) = self.position.last_mut() 2246 { 2247 // We are now expecting to see the specifiers list 2248 *expected = BitArraySegmentExpectedItem::Specifiers; 2249 if *segment_value_needs_wrapping { 2250 self.code.push(')'); 2251 *segment_value_needs_wrapping = false; 2252 } 2253 // We have the default atom as a size, that means we don't have to 2254 // print anything at all! The size doesn't need any wrapping because 2255 // there's no size at all. 2256 *segment_size_needs_wrapping = false; 2257 } else { 2258 invalid_code_for_position!(self, "segment default size"); 2259 } 2260 } 2261 2262 fn bit_array_segment_specifiers( 2263 &mut self, 2264 specifiers: impl IntoIterator<Item = BitArraySegmentSpecifier>, 2265 ) { 2266 self.pop_leftover_items(); 2267 let Some(ErlangSourceBuilderPosition::BitArraySegment { 2268 expected: BitArraySegmentExpectedItem::Specifiers, 2269 segment_value_needs_wrapping, 2270 segment_size_needs_wrapping, 2271 }) = self.position.last_mut() 2272 else { 2273 invalid_code_for_position!(self, "bit array segment specifier"); 2274 }; 2275 2276 if *segment_value_needs_wrapping { 2277 self.code.push(')'); 2278 *segment_value_needs_wrapping = false; 2279 } else if *segment_size_needs_wrapping { 2280 self.code.push(')'); 2281 *segment_size_needs_wrapping = false; 2282 } 2283 2284 let mut first_specifier = true; 2285 let specifiers = specifiers.into_iter().sorted_by(|one, other| { 2286 if let BitArraySegmentSpecifier::Unit(_) = one { 2287 std::cmp::Ordering::Greater 2288 } else if let BitArraySegmentSpecifier::Unit(_) = other { 2289 std::cmp::Ordering::Less 2290 } else { 2291 std::cmp::Ordering::Equal 2292 } 2293 }); 2294 2295 for specifier in specifiers { 2296 let string = match specifier { 2297 BitArraySegmentSpecifier::Utf8 => "utf8", 2298 BitArraySegmentSpecifier::Utf16 => "utf16", 2299 BitArraySegmentSpecifier::Utf32 => "utf32", 2300 BitArraySegmentSpecifier::Integer => "integer", 2301 BitArraySegmentSpecifier::Float => "float", 2302 BitArraySegmentSpecifier::Binary => "binary", 2303 BitArraySegmentSpecifier::Bitstring => "bitstring", 2304 BitArraySegmentSpecifier::Signed => "signed", 2305 BitArraySegmentSpecifier::Unsigned => "unsigned", 2306 BitArraySegmentSpecifier::Little => "little", 2307 BitArraySegmentSpecifier::Big => "big", 2308 BitArraySegmentSpecifier::Native => "native", 2309 BitArraySegmentSpecifier::Unit(unit) => &format!("unit:{unit}"), 2310 }; 2311 if first_specifier { 2312 first_specifier = false; 2313 self.code.push('/'); 2314 } else { 2315 self.code.push('-') 2316 } 2317 self.code.push_str(string); 2318 } 2319 2320 self.position.pop(); 2321 } 2322 2323 fn cons_list(&mut self) { 2324 self.cons_list_of_kind(ListKind::Expression); 2325 } 2326 2327 fn empty_list(&mut self) { 2328 self.empty_list_of_kind(ListKind::Expression); 2329 } 2330 2331 fn start_case(&mut self) -> Self::Case { 2332 self.new_expression(); 2333 self.code.push_str("case "); 2334 self.position.push(ErlangSourceBuilderPosition::Case { 2335 expected: ExpectedCaseItem::Subject, 2336 }); 2337 } 2338 2339 fn end_case_subject(&mut self, _case: Self::CaseSubject) -> Self::Case { 2340 // We need to make sure that just a single expression was generated as 2341 // the subject and then this function was called. 2342 // So we can assert that we're no longer expecting the subject but the 2343 // clauses and none has been generated yet. 2344 self.pop_leftover_items(); 2345 let Some(ErlangSourceBuilderPosition::Case { 2346 expected: ExpectedCaseItem::Branches { first: true }, 2347 }) = self.position.last() 2348 else { 2349 invalid_code_for_position!(self, "end case subject") 2350 }; 2351 } 2352 2353 fn end_case(&mut self, _case: Self::Case) { 2354 self.close_currently_open_item(); 2355 } 2356 2357 fn start_case_clause(&mut self) -> Self::ClausePattern { 2358 self.new_case_clause(); 2359 self.position.push(ErlangSourceBuilderPosition::CaseClause { 2360 expected: ExpectedCaseClauseItem::Pattern, 2361 }); 2362 } 2363 2364 fn end_clause_pattern(&mut self, _clause_pattern: Self::ClausePattern) -> Self::ClauseGuards { 2365 self.close_currently_open_item(); 2366 self.position.push(ErlangSourceBuilderPosition::CaseClause { 2367 expected: ExpectedCaseClauseItem::Guards { first: true }, 2368 }); 2369 } 2370 2371 fn start_clause_guard(&mut self) -> Self::Guard { 2372 self.new_clause_guard(); 2373 self.position.push(ErlangSourceBuilderPosition::ClauseGuard); 2374 } 2375 2376 fn end_clause_guard(&mut self, _clause_guard: Self::Guard) { 2377 self.close_currently_open_item(); 2378 } 2379 2380 fn end_clause_guards(&mut self, _clause_guards: Self::ClauseGuards) -> Self::ClauseBody { 2381 self.close_currently_open_item(); 2382 self.indentation += INDENT; 2383 self.position.push(ErlangSourceBuilderPosition::CaseClause { 2384 expected: ExpectedCaseClauseItem::Body { first: true }, 2385 }); 2386 } 2387 2388 fn end_clause_body(&mut self, _clause_body: Self::ClauseBody) { 2389 self.close_currently_open_item(); 2390 } 2391 2392 fn variable(&mut self, name: &str) { 2393 self.do_not_wrap_if_segment_value_or_size(); 2394 self.new_expression(); 2395 self.code.push_str(name); 2396 } 2397 2398 fn unary_operator(&mut self, operator: &str) { 2399 self.new_expression(); 2400 self.code.push_str(operator); 2401 self.code.push(' '); 2402 self.position 2403 .push(ErlangSourceBuilderPosition::UnaryOperator) 2404 } 2405 2406 fn binary_operator(&mut self, operator: &'static str) { 2407 self.pop_leftover_items(); 2408 2409 // If this new binary operator we're generating is part of a bigger 2410 // binary operator (it doesn't matter if on the left or right-hand 2411 // side), then we want to wrap it in parentheses to avoid precedence 2412 // confusion! 2413 let needs_wrapping = match self.position.last() { 2414 Some( 2415 ErlangSourceBuilderPosition::BinaryOperator { .. } 2416 | ErlangSourceBuilderPosition::UnaryOperator, 2417 ) => true, 2418 Some(_) | None => false, 2419 }; 2420 2421 self.new_expression(); 2422 if needs_wrapping { 2423 self.code.push('('); 2424 } 2425 self.position 2426 .push(ErlangSourceBuilderPosition::BinaryOperator { 2427 expected: ExpectedBinaryOperatorSide::Left, 2428 needs_wrapping, 2429 operator, 2430 }) 2431 } 2432 2433 fn function_reference(&mut self, module: Option<ErlangModuleName>, name: &str, arity: usize) { 2434 self.new_expression(); 2435 self.code.push_str("fun "); 2436 if let Some(module) = module { 2437 self.code.push_str(&quote_atom_name(&module.0)); 2438 self.code.push(':'); 2439 } 2440 self.code.push_str(&quote_atom_name(name)); 2441 self.code.push('/'); 2442 self.code.push_str(&arity.to_string()); 2443 } 2444 2445 fn match_operator(&mut self) { 2446 self.new_expression(); 2447 self.position 2448 .push(ErlangSourceBuilderPosition::MatchOperator { 2449 expected: ExpectedMatchSide::Pattern, 2450 }); 2451 } 2452 2453 fn match_pattern(&mut self) { 2454 self.new_pattern(); 2455 self.position 2456 .push(ErlangSourceBuilderPosition::MatchPattern { 2457 expected: ExpectedMatchPatternSide::Left, 2458 }) 2459 } 2460 2461 fn variable_pattern(&mut self, name: &str) { 2462 self.do_not_wrap_if_segment_value_or_size(); 2463 self.new_pattern(); 2464 self.code.push_str(name); 2465 } 2466 2467 fn discard_pattern(&mut self) { 2468 self.do_not_wrap_if_segment_value_or_size(); 2469 self.new_pattern(); 2470 self.code.push('_'); 2471 } 2472 2473 fn int_pattern(&mut self, number: BigInt) { 2474 self.do_not_wrap_if_segment_value_or_size(); 2475 self.new_pattern(); 2476 self.code.push_str(&number.to_string()); 2477 } 2478 2479 fn float_pattern(&mut self, number: f64) { 2480 self.do_not_wrap_if_segment_value_or_size(); 2481 self.new_pattern(); 2482 2483 self.code.push_str(&format_float(number)) 2484 } 2485 2486 fn string_pattern(&mut self, content: &str) { 2487 self.do_not_wrap_if_segment_value_or_size(); 2488 self.new_pattern(); 2489 self.do_print_string_content(content); 2490 } 2491 2492 fn atom_pattern(&mut self, name: &str) { 2493 self.new_pattern(); 2494 self.code.push_str(&quote_atom_name(name)); 2495 } 2496 2497 fn start_tuple_pattern(&mut self) -> Self::TuplePattern { 2498 self.new_pattern(); 2499 self.code.push('{'); 2500 self.position 2501 .push(ErlangSourceBuilderPosition::TuplePattern { first: true }); 2502 } 2503 2504 fn end_tuple_pattern(&mut self, _tuple: Self::TuplePattern) { 2505 self.close_currently_open_item(); 2506 } 2507 2508 fn start_bit_array_pattern(&mut self) -> Self::BitArrayPattern { 2509 self.new_pattern(); 2510 self.code.push_str("<<"); 2511 self.position.push(ErlangSourceBuilderPosition::BitArray { 2512 kind: BitArrayKind::Pattern, 2513 first: true, 2514 }); 2515 } 2516 2517 fn end_bit_array_pattern(&mut self, _bit_array: Self::BitArrayPattern) { 2518 self.close_currently_open_item(); 2519 } 2520 2521 fn cons_list_pattern(&mut self) { 2522 self.cons_list_of_kind(ListKind::Pattern); 2523 } 2524 2525 fn empty_list_pattern(&mut self) { 2526 self.empty_list_of_kind(ListKind::Pattern); 2527 } 2528 2529 fn string(&mut self, content: &str) { 2530 self.do_not_wrap_if_segment_value_or_size(); 2531 self.new_expression(); 2532 self.do_print_string_content(content); 2533 } 2534 2535 fn int(&mut self, number: BigInt) { 2536 self.do_not_wrap_if_segment_value_or_size(); 2537 self.new_expression(); 2538 self.code.push_str(&number.to_string()); 2539 } 2540 2541 fn float(&mut self, number: f64) { 2542 self.do_not_wrap_if_segment_value_or_size(); 2543 self.new_expression(); 2544 self.code.push_str(&format_float(number)); 2545 } 2546 2547 fn atom(&mut self, name: &str) { 2548 self.new_expression(); 2549 self.code.push_str(&quote_atom_name(name)); 2550 } 2551} 2552 2553fn format_float(number: f64) -> String { 2554 if number.is_zero() { 2555 if number.is_sign_negative() { 2556 String::from("-0.0") 2557 } else { 2558 String::from("+0.0") 2559 } 2560 } else if number.fract().is_zero() { 2561 format!("{number:.1}") 2562 } else { 2563 format!("{number}") 2564 } 2565} 2566 2567const INDENT: usize = 4; 2568 2569impl ErlangSourceBuilder { 2570 /// This has to be called before generating any new top level form: those 2571 /// are specs like `-spec`, `-type`, `-opaque`, doc attributes like 2572 /// `-doc` and `-moduledoc`, and function definitions. 2573 /// This allows the code generator to: 2574 /// - check for inconsistencies and panic (for example if we're generating 2575 /// a top level form not at the top level scope). 2576 /// - update the current context. 2577 /// - add all the code that needs to go before this expression we're about 2578 /// to generate, based on the current context. 2579 /// 2580 fn new_top_level_form(&mut self) { 2581 self.pop_leftover_items(); 2582 if !self.position.is_empty() { 2583 invalid_code_for_position!(self, "top level form"); 2584 } 2585 } 2586 2587 /// This has to be called before generating any expression! 2588 /// This allows the code generator to: 2589 /// - check for inconsistencies and panic (for example if we're generating 2590 /// expressions in the wrong place). 2591 /// - update the current context. 2592 /// - add all the code that needs to go before this expression we're about 2593 /// to generate, based on the current context. 2594 /// 2595 fn new_expression(&mut self) { 2596 self.pop_leftover_items(); 2597 let Some(position) = self.position.last_mut() else { 2598 invalid_code_for_position!(self, "expression"); 2599 }; 2600 2601 match position { 2602 ErlangSourceBuilderPosition::RecordField { 2603 expected: expected @ ExpectedRecordFieldItem::Name, 2604 } => *expected = ExpectedRecordFieldItem::Type, 2605 2606 ErlangSourceBuilderPosition::Case { 2607 expected: expected @ ExpectedCaseItem::Subject, 2608 } => *expected = ExpectedCaseItem::Branches { first: true }, 2609 2610 ErlangSourceBuilderPosition::FunctionCall { 2611 expected: expected @ ExpectedCallItem::FunctionToBeCalled, 2612 called_item_needs_wrapping, 2613 } => { 2614 if *called_item_needs_wrapping { 2615 self.code.push('('); 2616 }; 2617 *expected = ExpectedCallItem::Arguments { first: true } 2618 } 2619 2620 ErlangSourceBuilderPosition::FunctionCall { 2621 expected: ExpectedCallItem::Arguments { first }, 2622 called_item_needs_wrapping, 2623 } => { 2624 if *called_item_needs_wrapping { 2625 *called_item_needs_wrapping = false; 2626 self.code.push(')'); 2627 } 2628 if *first { 2629 self.code.push('(') 2630 } else { 2631 self.code.push_str(", "); 2632 } 2633 *first = false; 2634 } 2635 ErlangSourceBuilderPosition::Tuple { first } => { 2636 if !*first { 2637 self.code.push_str(", "); 2638 } 2639 *first = false; 2640 } 2641 2642 // We're expecting the list's head. We don't have to add 2643 // anything! 2644 ErlangSourceBuilderPosition::List { 2645 expected: expected @ ExpectedListItem::First, 2646 kind: ListKind::Expression, 2647 } => *expected = ExpectedListItem::Rest, 2648 2649 ErlangSourceBuilderPosition::List { 2650 expected: expected @ ExpectedListItem::Rest, 2651 kind: ListKind::Expression, 2652 } => { 2653 *expected = ExpectedListItem::ListIsOver; 2654 self.code.push_str(" | ") 2655 } 2656 2657 ErlangSourceBuilderPosition::BinaryOperator { 2658 expected: expected @ ExpectedBinaryOperatorSide::Left, 2659 .. 2660 } => *expected = ExpectedBinaryOperatorSide::Right, 2661 2662 ErlangSourceBuilderPosition::BinaryOperator { 2663 expected: expected @ ExpectedBinaryOperatorSide::Right, 2664 operator, 2665 .. 2666 } => { 2667 *expected = ExpectedBinaryOperatorSide::BinaryOperatorIsOver; 2668 self.code.push(' '); 2669 self.code.push_str(operator); 2670 self.code.push(' '); 2671 } 2672 2673 ErlangSourceBuilderPosition::FunctionStatement { first } 2674 | ErlangSourceBuilderPosition::AnonymousFunctionStatement { first } 2675 | ErlangSourceBuilderPosition::Block { first } 2676 | ErlangSourceBuilderPosition::CaseClause { 2677 expected: ExpectedCaseClauseItem::Body { first }, 2678 } => { 2679 if !*first { 2680 self.code.push(','); 2681 } 2682 *first = false; 2683 self.code.push('\n'); 2684 self.push_indentation(); 2685 } 2686 2687 ErlangSourceBuilderPosition::BitArraySegment { 2688 expected: 2689 expected @ BitArraySegmentExpectedItem::Value { 2690 kind: BitArrayKind::Expression, 2691 }, 2692 segment_value_needs_wrapping, 2693 .. 2694 } => { 2695 if *segment_value_needs_wrapping { 2696 self.code.push('('); 2697 } 2698 *expected = BitArraySegmentExpectedItem::Size 2699 } 2700 2701 ErlangSourceBuilderPosition::BitArraySegment { 2702 expected: expected @ BitArraySegmentExpectedItem::Size, 2703 segment_value_needs_wrapping, 2704 segment_size_needs_wrapping, 2705 } => { 2706 if *segment_value_needs_wrapping { 2707 self.code.push(')'); 2708 // We've finished wrapping the value, we set this to 2709 // false so we don't add other parentheses when we get 2710 // to the specifiers list! 2711 *segment_value_needs_wrapping = false; 2712 } 2713 *expected = BitArraySegmentExpectedItem::Specifiers; 2714 self.code.push(':'); 2715 if *segment_size_needs_wrapping { 2716 self.code.push('('); 2717 } 2718 } 2719 2720 ErlangSourceBuilderPosition::ClauseGuard => { 2721 self.code.push_str(" when "); 2722 } 2723 2724 ErlangSourceBuilderPosition::MapField { expected } => match expected { 2725 MapFieldExpectedItem::Key => *expected = MapFieldExpectedItem::Value, 2726 // We've generated a key and now the value is being generated. 2727 // So we need to add the `=>` separating key and value and we 2728 // can pop this position that is now complete. 2729 MapFieldExpectedItem::Value => { 2730 self.code.push_str(" => "); 2731 self.position.pop(); 2732 } 2733 }, 2734 2735 // We were expecting an expression and someone is about to generate 2736 // it, we can pop this off the stack and need to add the ` = ` 2737 // separating the previous pattern from this new expression. 2738 ErlangSourceBuilderPosition::MatchOperator { 2739 expected: ExpectedMatchSide::Expression, 2740 } => { 2741 self.code.push_str(" = "); 2742 self.position.pop(); 2743 } 2744 // We were expecting an expression and someone generated it, we can 2745 // now pop this off the stack. 2746 ErlangSourceBuilderPosition::UnaryOperator => { 2747 self.position.pop(); 2748 } 2749 2750 // Expressions are not allowed in any of these positions. 2751 ErlangSourceBuilderPosition::Case { 2752 expected: ExpectedCaseItem::Branches { .. }, 2753 } 2754 | ErlangSourceBuilderPosition::List { 2755 expected: ExpectedListItem::ListIsOver, 2756 kind: ListKind::Expression, 2757 } 2758 | ErlangSourceBuilderPosition::BitArray { .. } 2759 | ErlangSourceBuilderPosition::MatchOperator { 2760 expected: ExpectedMatchSide::Pattern, 2761 } 2762 | ErlangSourceBuilderPosition::CaseClause { 2763 expected: ExpectedCaseClauseItem::Pattern, 2764 } 2765 | ErlangSourceBuilderPosition::TuplePattern { .. } 2766 | ErlangSourceBuilderPosition::MatchPattern { .. } 2767 | ErlangSourceBuilderPosition::FunctionSpec 2768 | ErlangSourceBuilderPosition::TypeSpec { .. } 2769 | ErlangSourceBuilderPosition::NamedType { .. } 2770 | ErlangSourceBuilderPosition::FunctionType { .. } 2771 | ErlangSourceBuilderPosition::UnionType { .. } 2772 | ErlangSourceBuilderPosition::RecordField { 2773 expected: ExpectedRecordFieldItem::Type, 2774 } 2775 | ErlangSourceBuilderPosition::TupleType { .. } 2776 | ErlangSourceBuilderPosition::Map { .. } 2777 | ErlangSourceBuilderPosition::RecordAttribute { .. } 2778 | ErlangSourceBuilderPosition::CaseClause { 2779 expected: ExpectedCaseClauseItem::Guards { .. }, 2780 } 2781 | ErlangSourceBuilderPosition::BitArraySegment { 2782 expected: BitArraySegmentExpectedItem::Specifiers, 2783 .. 2784 } 2785 | ErlangSourceBuilderPosition::BitArraySegment { 2786 expected: 2787 BitArraySegmentExpectedItem::Value { 2788 kind: BitArrayKind::Pattern, 2789 }, 2790 .. 2791 } 2792 | ErlangSourceBuilderPosition::BinaryOperator { 2793 expected: ExpectedBinaryOperatorSide::BinaryOperatorIsOver, 2794 .. 2795 } 2796 | ErlangSourceBuilderPosition::List { 2797 kind: ListKind::Pattern, 2798 .. 2799 } => invalid_code_for_position!(self, "expression"), 2800 } 2801 } 2802 2803 /// This has to be called before generating any type! 2804 /// This allows the code generator to: 2805 /// - check for inconsistencies and panic (for example if we're generating 2806 /// types in the wrong place). 2807 /// - update the current context. 2808 /// - add all the code that needs to go before this type we're about 2809 /// to generate, based on the current context. 2810 /// 2811 fn new_type(&mut self) { 2812 self.pop_leftover_items(); 2813 let Some(position) = self.position.last_mut() else { 2814 invalid_code_for_position!(self, "type"); 2815 }; 2816 2817 match position { 2818 ErlangSourceBuilderPosition::FunctionSpec => {} 2819 ErlangSourceBuilderPosition::FunctionType { 2820 expected: ExpectedFunctionTypeItem::ReturnType, 2821 needs_wrapping: _, 2822 } => {} 2823 2824 ErlangSourceBuilderPosition::TypeSpec { 2825 expected: expected @ TypeSpecExpectedItem::TypeDefinition, 2826 } => { 2827 *expected = TypeSpecExpectedItem::TypeSpecIsOver; 2828 } 2829 2830 ErlangSourceBuilderPosition::FunctionType { 2831 expected: ExpectedFunctionTypeItem::Arguments { first }, 2832 needs_wrapping: _, 2833 } 2834 | ErlangSourceBuilderPosition::TupleType { first } 2835 | ErlangSourceBuilderPosition::NamedType { first } => { 2836 if !*first { 2837 self.code.push_str(", ") 2838 } 2839 *first = false 2840 } 2841 2842 ErlangSourceBuilderPosition::UnionType { first } => { 2843 if !*first { 2844 self.code.push_str(" | ") 2845 } 2846 *first = false 2847 } 2848 2849 ErlangSourceBuilderPosition::RecordField { 2850 expected: ExpectedRecordFieldItem::Type, 2851 } => { 2852 self.code.push_str(" :: "); 2853 self.position.pop(); 2854 } 2855 2856 ErlangSourceBuilderPosition::FunctionCall { .. } 2857 | ErlangSourceBuilderPosition::Block { .. } 2858 | ErlangSourceBuilderPosition::Tuple { .. } 2859 | ErlangSourceBuilderPosition::BitArray { .. } 2860 | ErlangSourceBuilderPosition::BitArraySegment { .. } 2861 | ErlangSourceBuilderPosition::List { .. } 2862 | ErlangSourceBuilderPosition::FunctionStatement { .. } 2863 | ErlangSourceBuilderPosition::AnonymousFunctionStatement { .. } 2864 | ErlangSourceBuilderPosition::UnaryOperator 2865 | ErlangSourceBuilderPosition::Case { .. } 2866 | ErlangSourceBuilderPosition::ClauseGuard 2867 | ErlangSourceBuilderPosition::BinaryOperator { .. } 2868 | ErlangSourceBuilderPosition::CaseClause { .. } 2869 | ErlangSourceBuilderPosition::Map { .. } 2870 | ErlangSourceBuilderPosition::MapField { .. } 2871 | ErlangSourceBuilderPosition::RecordField { 2872 expected: ExpectedRecordFieldItem::Name, 2873 } 2874 | ErlangSourceBuilderPosition::MatchOperator { 2875 expected: ExpectedMatchSide::Expression, 2876 } 2877 | ErlangSourceBuilderPosition::RecordAttribute { .. } 2878 | ErlangSourceBuilderPosition::TypeSpec { 2879 expected: TypeSpecExpectedItem::TypeSpecIsOver, 2880 } 2881 | ErlangSourceBuilderPosition::MatchOperator { 2882 expected: ExpectedMatchSide::Pattern, 2883 } 2884 | ErlangSourceBuilderPosition::MatchPattern { .. } 2885 | ErlangSourceBuilderPosition::TuplePattern { .. } => { 2886 invalid_code_for_position!(self, "type") 2887 } 2888 } 2889 } 2890 2891 /// This has to be called before generating any pattern! 2892 /// This allows the code generator to: 2893 /// - check for inconsistencies and panic (for example if we're generating 2894 /// patterns in the wrong place). 2895 /// - update the current context. 2896 /// - add all the code that needs to go before this type we're about 2897 /// to generate, based on the current context. 2898 /// 2899 fn new_pattern(&mut self) { 2900 self.pop_leftover_items(); 2901 let Some(position) = self.position.last_mut() else { 2902 invalid_code_for_position!(self, "pattern"); 2903 }; 2904 2905 match position { 2906 // We're expecting the list's head. We don't have to add 2907 // anything! 2908 ErlangSourceBuilderPosition::List { 2909 kind: ListKind::Pattern, 2910 expected: expected @ ExpectedListItem::First, 2911 } => *expected = ExpectedListItem::Rest, 2912 2913 ErlangSourceBuilderPosition::List { 2914 kind: ListKind::Pattern, 2915 expected: expected @ ExpectedListItem::Rest, 2916 } => { 2917 *expected = ExpectedListItem::ListIsOver; 2918 self.code.push_str(" | ") 2919 } 2920 2921 ErlangSourceBuilderPosition::BitArraySegment { 2922 segment_value_needs_wrapping, 2923 segment_size_needs_wrapping: _, 2924 expected: 2925 expected @ BitArraySegmentExpectedItem::Value { 2926 kind: BitArrayKind::Pattern, 2927 }, 2928 } => { 2929 if *segment_value_needs_wrapping { 2930 self.code.push('('); 2931 } 2932 *expected = BitArraySegmentExpectedItem::Size 2933 } 2934 2935 // We were waiting for the pattern to be generated, now we're done 2936 // and can start generating an expression for the right-hand side. 2937 ErlangSourceBuilderPosition::MatchOperator { 2938 expected: expected @ ExpectedMatchSide::Pattern, 2939 } => { 2940 *expected = ExpectedMatchSide::Expression; 2941 } 2942 2943 // We were waiting for the pattern and a pattern has been generated. 2944 // We don't change this ourselves since the pattern has to be closed 2945 // explicitly calling `end_clause_pattern`. 2946 // We don't have to do anything here! 2947 ErlangSourceBuilderPosition::CaseClause { 2948 expected: ExpectedCaseClauseItem::Pattern, 2949 } => (), 2950 ErlangSourceBuilderPosition::TuplePattern { first } => { 2951 if *first { 2952 *first = false; 2953 } else { 2954 self.code.push_str(", ") 2955 } 2956 } 2957 ErlangSourceBuilderPosition::MatchPattern { expected } => match expected { 2958 ExpectedMatchPatternSide::Left => *expected = ExpectedMatchPatternSide::Right, 2959 // The right hand side is about to be generated so we have to 2960 // push the ` = ` to separate it from the left hand side, and we 2961 // can remove this position since the match pattern has now been 2962 // completed. 2963 ExpectedMatchPatternSide::Right => { 2964 self.code.push_str(" = "); 2965 self.position.pop(); 2966 } 2967 }, 2968 2969 ErlangSourceBuilderPosition::FunctionCall { .. } 2970 | ErlangSourceBuilderPosition::Block { .. } 2971 | ErlangSourceBuilderPosition::FunctionStatement { .. } 2972 | ErlangSourceBuilderPosition::AnonymousFunctionStatement { .. } 2973 | ErlangSourceBuilderPosition::List { 2974 kind: ListKind::Expression, 2975 .. 2976 } 2977 | ErlangSourceBuilderPosition::BitArray { .. } 2978 | ErlangSourceBuilderPosition::BitArraySegment { 2979 expected: 2980 BitArraySegmentExpectedItem::Size 2981 | BitArraySegmentExpectedItem::Specifiers 2982 | BitArraySegmentExpectedItem::Value { 2983 kind: BitArrayKind::Expression, 2984 }, 2985 .. 2986 } 2987 | ErlangSourceBuilderPosition::UnaryOperator 2988 | ErlangSourceBuilderPosition::BinaryOperator { .. } 2989 | ErlangSourceBuilderPosition::Case { .. } 2990 | ErlangSourceBuilderPosition::ClauseGuard 2991 | ErlangSourceBuilderPosition::Map { .. } 2992 | ErlangSourceBuilderPosition::MapField { .. } 2993 | ErlangSourceBuilderPosition::MatchOperator { 2994 expected: ExpectedMatchSide::Expression, 2995 } 2996 | ErlangSourceBuilderPosition::Tuple { .. } 2997 | ErlangSourceBuilderPosition::FunctionType { .. } 2998 | ErlangSourceBuilderPosition::FunctionSpec 2999 | ErlangSourceBuilderPosition::TypeSpec { .. } 3000 | ErlangSourceBuilderPosition::NamedType { .. } 3001 | ErlangSourceBuilderPosition::UnionType { .. } 3002 | ErlangSourceBuilderPosition::TupleType { .. } 3003 | ErlangSourceBuilderPosition::RecordField { .. } 3004 | ErlangSourceBuilderPosition::RecordAttribute { .. } 3005 | ErlangSourceBuilderPosition::List { 3006 kind: ListKind::Pattern, 3007 expected: ExpectedListItem::ListIsOver, 3008 } 3009 | ErlangSourceBuilderPosition::CaseClause { 3010 expected: ExpectedCaseClauseItem::Guards { .. }, 3011 } 3012 | ErlangSourceBuilderPosition::CaseClause { 3013 expected: ExpectedCaseClauseItem::Body { .. }, 3014 } => { 3015 invalid_code_for_position!(self, "pattern"); 3016 } 3017 } 3018 } 3019 3020 fn close_currently_open_item(&mut self) { 3021 self.pop_leftover_items(); 3022 let Some(position) = self.position.pop() else { 3023 return; 3024 }; 3025 3026 match position { 3027 // When we're done generating statements for a function we need to 3028 // add one final `.` to the last statement. Then we also want to 3029 // add an empty line to make our code breath a bit better. 3030 ErlangSourceBuilderPosition::FunctionStatement { .. } => { 3031 self.indentation -= INDENT; 3032 self.code.push_str(".\n") 3033 } 3034 // When we're done generating statements for an anonymous function 3035 // we need to add the closing `end` after the last statement on a 3036 // new line. 3037 ErlangSourceBuilderPosition::AnonymousFunctionStatement { .. } => { 3038 self.indentation -= INDENT; 3039 self.code.push('\n'); 3040 self.push_indentation(); 3041 self.code.push_str("end") 3042 } 3043 // When we're done generating statements for a block we need to add 3044 // the closing `end`, and reduce the nesting level. 3045 ErlangSourceBuilderPosition::Block { .. } => { 3046 self.indentation -= INDENT; 3047 self.code.push('\n'); 3048 self.push_indentation(); 3049 self.code.push_str("end"); 3050 } 3051 // When we're done generating code for a function spec we want to 3052 // add a `.` and go to a new line so we can start generating the 3053 // function itself. 3054 ErlangSourceBuilderPosition::FunctionSpec => self.code.push_str(".\n"), 3055 // When we're done generating the arguments of a function we need 3056 // to add the closed parentheses for the function call! 3057 ErlangSourceBuilderPosition::FunctionCall { 3058 expected: ExpectedCallItem::Arguments { first }, 3059 called_item_needs_wrapping, 3060 } => { 3061 if called_item_needs_wrapping { 3062 self.code.push(')') 3063 } 3064 3065 // If the function is closed with no arguments being generated 3066 // then we will need to add both the open and closed 3067 // parentheses. That's because the open paren is added when the 3068 // first argument is generated. 3069 if first { 3070 self.code.push_str("()") 3071 } else { 3072 self.code.push(')') 3073 } 3074 } 3075 3076 // When we're done generating the items of a tuple we need 3077 // to add the closed curly brace to actually close the tuple. 3078 ErlangSourceBuilderPosition::TupleType { .. } 3079 | ErlangSourceBuilderPosition::Tuple { .. } 3080 | ErlangSourceBuilderPosition::TuplePattern { .. } => self.code.push('}'), 3081 // When we're done generating a bit array we can add its closing 3082 // element. 3083 ErlangSourceBuilderPosition::BitArray { .. } => self.code.push_str(">>"), 3084 3085 // When the function type arguments are over we add what we need for 3086 // the return type. 3087 ErlangSourceBuilderPosition::FunctionType { 3088 expected: ExpectedFunctionTypeItem::Arguments { .. }, 3089 needs_wrapping, 3090 } => { 3091 // After popping the argument, we now need to wait for the 3092 // return type! 3093 self.position 3094 .push(ErlangSourceBuilderPosition::FunctionType { 3095 expected: ExpectedFunctionTypeItem::ReturnType, 3096 needs_wrapping, 3097 }); 3098 self.code.push_str(") -> ") 3099 } 3100 // When a named type is over we need to add the closing parentheses. 3101 ErlangSourceBuilderPosition::NamedType { .. } => self.code.push(')'), 3102 // If we close a function type we need to check what the current 3103 // state is. If we were generating this for a type spec we're done. 3104 // But if we were generating this as a type inside another we need to 3105 // add one further parentheses to close the `fun(...)` around the 3106 // function type. 3107 // 3108 // ```erl 3109 // % in a spec annotation it simply comes after the function name: 3110 // -spec wibble () -> integer(). 3111 // wibble() -> 11. 3112 // 3113 // % but inside another type it has to be wrapped in `fun(...)`: 3114 // -spec wobble () -> fun(() -> integer()) 3115 // % ^ We're adding this bit here! 3116 // wobble() -> fun wibble/0. 3117 // ``` 3118 ErlangSourceBuilderPosition::FunctionType { 3119 expected: ExpectedFunctionTypeItem::ReturnType, 3120 needs_wrapping, 3121 } => { 3122 if needs_wrapping { 3123 self.code.push(')') 3124 } 3125 } 3126 // There's nothing left to do when a union type ends. 3127 ErlangSourceBuilderPosition::UnionType { .. } => (), 3128 // When a case expression is over, we need to add the closing `end`. 3129 ErlangSourceBuilderPosition::Case { 3130 expected: ExpectedCaseItem::Branches { .. }, 3131 } => { 3132 self.indentation -= INDENT; 3133 self.code.push('\n'); 3134 self.push_indentation(); 3135 self.code.push_str("end"); 3136 } 3137 3138 ErlangSourceBuilderPosition::ClauseGuard => (), 3139 ErlangSourceBuilderPosition::CaseClause { expected } => match expected { 3140 ExpectedCaseClauseItem::Pattern => (), 3141 // When the guards of a case clause are over we need to add the 3142 // arrow before the body is generated. 3143 ExpectedCaseClauseItem::Guards { .. } => self.code.push_str(" ->"), 3144 ExpectedCaseClauseItem::Body { .. } => { 3145 self.indentation -= INDENT; 3146 } 3147 }, 3148 // We're done with a map, we can add the closed parentheses and 3149 // reduce nesting. 3150 ErlangSourceBuilderPosition::Map { .. } => { 3151 self.indentation -= INDENT; 3152 self.code.push('\n'); 3153 self.push_indentation(); 3154 self.code.push('}'); 3155 } 3156 ErlangSourceBuilderPosition::RecordAttribute { .. } => { 3157 self.indentation -= INDENT; 3158 self.code.push('\n'); 3159 self.push_indentation(); 3160 self.code.push_str("})."); 3161 } 3162 3163 ErlangSourceBuilderPosition::MapField { .. } 3164 | ErlangSourceBuilderPosition::RecordField { .. } 3165 | ErlangSourceBuilderPosition::MatchPattern { .. } 3166 | ErlangSourceBuilderPosition::UnaryOperator 3167 | ErlangSourceBuilderPosition::List { .. } 3168 | ErlangSourceBuilderPosition::BinaryOperator { .. } 3169 | ErlangSourceBuilderPosition::MatchOperator { .. } 3170 | ErlangSourceBuilderPosition::TypeSpec { .. } 3171 | ErlangSourceBuilderPosition::BitArraySegment { .. } 3172 | ErlangSourceBuilderPosition::Case { 3173 expected: ExpectedCaseItem::Subject, 3174 } 3175 | ErlangSourceBuilderPosition::FunctionCall { 3176 // If we try and close a function for which no called item was 3177 // generated, then that's an error! 3178 expected: ExpectedCallItem::FunctionToBeCalled, 3179 .. 3180 } => invalid_code_for_position!(self, "pop leftover item"), 3181 } 3182 } 3183 3184 /// Given the content of something that has to end up inside an Erlang 3185 /// literal string `~"..."` this escapes its content based on 3186 /// position-specific rules: depending where we will be putting the string 3187 /// (and so depending where it comes from) it might need different things to 3188 /// be escaped! 3189 /// 3190 /// For example, if we're given the content of a literal Gleam string, we 3191 /// know that some charachters like double quotes are going to be escaped 3192 /// already: 3193 /// 3194 /// ```gleam 3195 /// let some_gleam_string = "wibble\"wobble" 3196 /// ``` 3197 /// 3198 /// After all, if those weren't escaped our Gleam program would have a 3199 /// syntax error and not compile! 3200 /// 3201 /// However, there's other pieces of syntax that might be turned into 3202 /// literal Erlang strings: doc comments. In that case those can contain 3203 /// unescaped characters. For example: 3204 /// 3205 /// ```gleam 3206 /// /// This is a doc comment that has unescaped double quotes "" 3207 /// ``` 3208 /// 3209 /// If we were to just take that comment's content and put it in an Erlang 3210 /// string with no escaping that would produce invalid code! 3211 /// 3212 fn escape_string_content(&self, content: &str) -> String { 3213 let position = self 3214 .position 3215 .last() 3216 .expect("escaping string in the top level scope"); 3217 3218 match position { 3219 ErlangSourceBuilderPosition::FunctionSpec 3220 | ErlangSourceBuilderPosition::TypeSpec { .. } 3221 | ErlangSourceBuilderPosition::FunctionType { .. } 3222 | ErlangSourceBuilderPosition::NamedType { .. } 3223 | ErlangSourceBuilderPosition::UnionType { .. } 3224 | ErlangSourceBuilderPosition::RecordAttribute { .. } 3225 | ErlangSourceBuilderPosition::TupleType { .. } => { 3226 invalid_code_for_position!(self, "escaping string") 3227 } 3228 3229 ErlangSourceBuilderPosition::FunctionCall { .. } 3230 | ErlangSourceBuilderPosition::FunctionStatement { .. } 3231 | ErlangSourceBuilderPosition::AnonymousFunctionStatement { .. } 3232 | ErlangSourceBuilderPosition::List { .. } 3233 | ErlangSourceBuilderPosition::UnaryOperator 3234 | ErlangSourceBuilderPosition::Tuple { .. } 3235 | ErlangSourceBuilderPosition::TuplePattern { .. } 3236 | ErlangSourceBuilderPosition::BitArray { .. } 3237 | ErlangSourceBuilderPosition::BitArraySegment { .. } 3238 | ErlangSourceBuilderPosition::Block { .. } 3239 | ErlangSourceBuilderPosition::BinaryOperator { .. } 3240 | ErlangSourceBuilderPosition::Case { .. } 3241 | ErlangSourceBuilderPosition::CaseClause { .. } 3242 | ErlangSourceBuilderPosition::ClauseGuard 3243 | ErlangSourceBuilderPosition::Map { .. } 3244 | ErlangSourceBuilderPosition::MapField { .. } 3245 | ErlangSourceBuilderPosition::MatchPattern { .. } 3246 | ErlangSourceBuilderPosition::RecordField { .. } 3247 | ErlangSourceBuilderPosition::MatchOperator { .. } => { 3248 // When pretty printing we want the resulting code to be regular 3249 // executable Erlang code. 3250 // If we're tasked with escaping the content of a literal string 3251 // expression we need to turn Gleam's `\u` sequences into 3252 // Erlang's `\x`. 3253 UNICODE_ESCAPE_SEQUENCE_PATTERN 3254 .get_or_init(|| { 3255 Regex::new(r#"(\\+)(u)"#) 3256 .expect("Unicode escape sequence regex cannot be constructed") 3257 }) 3258 // `\\u`-s should not be affected, so that "\\u..." is not converted to 3259 // "\\x...". That's why capturing groups is used to exclude cases that 3260 // shouldn't be replaced. 3261 .replace_all(content, |caps: &regex::Captures<'_>| { 3262 let slashes = caps.get(1).map_or("", |match_| match_.as_str()); 3263 if slashes.len().is_multiple_of(2) { 3264 format!("{slashes}u") 3265 } else { 3266 format!("{slashes}x") 3267 } 3268 }) 3269 .into() 3270 } 3271 } 3272 } 3273 3274 #[must_use] 3275 fn new_bit_array_segment(&mut self) -> BitArrayKind { 3276 self.pop_leftover_items(); 3277 let Some(ErlangSourceBuilderPosition::BitArray { first, kind }) = self.position.last_mut() 3278 else { 3279 invalid_code_for_position!(self, "bit array segment") 3280 }; 3281 3282 if *first { 3283 *first = false; 3284 } else { 3285 self.code.push_str(", "); 3286 } 3287 3288 *kind 3289 } 3290 3291 fn new_case_clause(&mut self) { 3292 self.pop_leftover_items(); 3293 let Some(ErlangSourceBuilderPosition::Case { 3294 expected: ExpectedCaseItem::Branches { first }, 3295 }) = self.position.last_mut() 3296 else { 3297 invalid_code_for_position!(self, "case clause") 3298 }; 3299 3300 if *first { 3301 *first = false; 3302 self.code.push_str(" of\n"); 3303 self.indentation += INDENT; 3304 } else { 3305 self.code.push_str(";\n\n"); 3306 } 3307 self.code.push_str(&" ".repeat(self.indentation)) 3308 } 3309 3310 fn new_map_field(&mut self) { 3311 self.pop_leftover_items(); 3312 let Some(ErlangSourceBuilderPosition::Map { first }) = self.position.last_mut() else { 3313 invalid_code_for_position!(self, "map field"); 3314 }; 3315 3316 if *first { 3317 *first = false; 3318 self.code.push('\n'); 3319 } else { 3320 self.code.push_str(",\n") 3321 } 3322 self.code.push_str(&" ".repeat(self.indentation)) 3323 } 3324 3325 fn new_clause_guard(&mut self) { 3326 self.pop_leftover_items(); 3327 let Some(ErlangSourceBuilderPosition::CaseClause { 3328 expected: 3329 ExpectedCaseClauseItem::Guards { 3330 first: first @ true, 3331 }, 3332 }) = self.position.last_mut() 3333 else { 3334 invalid_code_for_position!(self, "new clause guard"); 3335 }; 3336 3337 *first = false; 3338 } 3339 3340 /// You can call this before generating any expression (before the 3341 /// `new_expression` call) if we can skip wrapping it in parentheses when it 3342 /// appears as a bitstring segment value. 3343 /// This is opt-out rather than opt-in: it's always safe to wrap everything, 3344 /// but it leads to slightly uglier code for some values like bare integers. 3345 /// For example: 3346 /// 3347 /// ```erl 3348 /// <<(1)/signed>> 3349 /// % ^ ^ Those are not needed at all! 3350 /// ``` 3351 /// 3352 /// So for those values that you know are safe and would look better you can 3353 /// use this function. 3354 /// 3355 fn do_not_wrap_if_segment_value_or_size(&mut self) { 3356 self.pop_leftover_items(); 3357 // If we're about to generate a bit array segment value, or a size, 3358 // then we can skip the wrapping, otherwise this is not needed at all! 3359 match self.position.last_mut() { 3360 Some(ErlangSourceBuilderPosition::BitArraySegment { 3361 segment_value_needs_wrapping, 3362 expected: BitArraySegmentExpectedItem::Value { .. }, 3363 .. 3364 }) => *segment_value_needs_wrapping = false, 3365 Some(ErlangSourceBuilderPosition::BitArraySegment { 3366 segment_size_needs_wrapping, 3367 expected: BitArraySegmentExpectedItem::Size, 3368 .. 3369 }) => *segment_size_needs_wrapping = false, 3370 _ => (), 3371 } 3372 } 3373 3374 /// This can be used to output the content of a string wether that is a 3375 /// pattern or an expression! 3376 fn do_print_string_content(&mut self, content: &str) { 3377 let content = self.escape_string_content(content); 3378 // If we're generating a string as a bit array segment value we want to 3379 // output slightly different code: rather than a bit array we want to 3380 // output a regular string with no modifiers which are going to be added 3381 // later as the segment is created 3382 if let Some(ErlangSourceBuilderPosition::BitArraySegment { 3383 // the call to `new_expression` at the beginning is going to advance 3384 // the state to expect the `::Size`, that means the code we are 3385 // outputting now was expected to be the the `::Value` of the bit 3386 // array segment! 3387 // We can't move the `new_expression` call down, that _must_ be the 3388 // first thing we do, so we check to see if the size if the next 3389 // thing we're expecting to see. 3390 expected: BitArraySegmentExpectedItem::Size, 3391 segment_value_needs_wrapping: _, 3392 segment_size_needs_wrapping: _, 3393 }) = self.position.last() 3394 { 3395 self.code.push('"'); 3396 self.code.push_str(&content); 3397 self.code.push('"'); 3398 } else { 3399 self.code.push_str("~\""); 3400 self.code.push_str(&content); 3401 self.code.push('"'); 3402 } 3403 } 3404 3405 fn cons_list_of_kind(&mut self, list_kind: ListKind) { 3406 self.pop_leftover_items(); 3407 match self.position.last_mut() { 3408 // If we were expecting the rest of a list and we generate a new 3409 // cons cell we can keep adding commas to separate items: we want 3410 // to show `[1, 2, 3]` rather than `[1 | [2 | [3 | []]]]` 3411 Some(ErlangSourceBuilderPosition::List { 3412 kind, 3413 expected: expected @ ExpectedListItem::Rest, 3414 }) if *kind == list_kind => { 3415 *expected = ExpectedListItem::First; 3416 self.code.push_str(", "); 3417 } 3418 // Otherwise we have to properly start a new list: push the `[` and 3419 // wait for the first item to be generated. 3420 Some(_) | None => { 3421 match list_kind { 3422 ListKind::Pattern => self.new_pattern(), 3423 ListKind::Expression => self.new_expression(), 3424 } 3425 self.code.push('['); 3426 self.position.push(ErlangSourceBuilderPosition::List { 3427 kind: list_kind, 3428 expected: ExpectedListItem::First, 3429 }); 3430 } 3431 } 3432 } 3433 3434 fn empty_list_of_kind(&mut self, list_kind: ListKind) { 3435 self.pop_leftover_items(); 3436 match self.position.last_mut() { 3437 // If we were building a cons list and were expecting the end of the 3438 // list then we have to special case this: we don't want to render 3439 // it as: `[1, 2 | []]`, but as `[1, 2]`. 3440 Some(ErlangSourceBuilderPosition::List { 3441 kind, 3442 expected: ExpectedListItem::Rest, 3443 }) if *kind == list_kind => { 3444 // Crucially we don't want to call `new_expression` here: we 3445 // don't want the default handling. 3446 self.code.push(']'); 3447 // The list is over, so we pop it away. 3448 self.position.pop(); 3449 } 3450 Some(_) | None => { 3451 match list_kind { 3452 ListKind::Pattern => self.new_pattern(), 3453 ListKind::Expression => self.new_expression(), 3454 } 3455 self.code.push_str("[]"); 3456 } 3457 } 3458 } 3459 3460 /// This has to be called before any `new_x` function. This takes care of 3461 /// removing all leftover items that do not self close. 3462 /// 3463 /// That happens when there's some node that requires code to be pushed 3464 /// _after_ it is over and it is not closed manually with a `end_x` 3465 /// function. 3466 fn pop_leftover_items(&mut self) { 3467 let Some(position) = self.position.last() else { 3468 return; 3469 }; 3470 3471 match position { 3472 ErlangSourceBuilderPosition::TypeSpec { 3473 expected: TypeSpecExpectedItem::TypeSpecIsOver, 3474 } => { 3475 self.code.push_str(".\n"); 3476 self.position.pop(); 3477 self.pop_leftover_items(); 3478 } 3479 3480 // The expression we're generating is preceded by a list 3481 // that has been closed. Lists are a bit tricky because they 3482 // are built as a list of cons cells, so we can't really 3483 // tell when a list is over until we get to the next 3484 // expression. 3485 ErlangSourceBuilderPosition::List { 3486 expected: ExpectedListItem::ListIsOver, 3487 .. 3488 } => { 3489 self.code.push(']'); 3490 // We remove this leftover list... 3491 self.position.pop(); 3492 // ...and then we can keep going until there's no leftover 3493 // items left. 3494 self.pop_leftover_items(); 3495 } 3496 3497 // Like with lists, we don't really know when a binary operator is 3498 // over until we get to the following operation (or we try closing 3499 // the current item and notice there's a closed operator left). 3500 // Also, just like lists, we might still need to add some 3501 // parentheses _after_ the operator is over. 3502 ErlangSourceBuilderPosition::BinaryOperator { 3503 expected: ExpectedBinaryOperatorSide::BinaryOperatorIsOver, 3504 needs_wrapping, 3505 .. 3506 } => { 3507 // If needed add the closing parentheses... 3508 if *needs_wrapping { 3509 self.code.push(')'); 3510 } 3511 // ...we remove this leftover binary operator... 3512 self.position.pop(); 3513 // ...and then we can keep going until there's no leftover items 3514 // left. 3515 self.pop_leftover_items(); 3516 } 3517 3518 // All of these items are not leftovers. They are either still open, 3519 // require manual closing, or things that don't need closing at all! 3520 ErlangSourceBuilderPosition::NamedType { .. } 3521 | ErlangSourceBuilderPosition::UnionType { .. } 3522 | ErlangSourceBuilderPosition::TupleType { .. } 3523 | ErlangSourceBuilderPosition::FunctionStatement { .. } 3524 | ErlangSourceBuilderPosition::AnonymousFunctionStatement { .. } 3525 | ErlangSourceBuilderPosition::FunctionSpec 3526 | ErlangSourceBuilderPosition::Tuple { .. } 3527 | ErlangSourceBuilderPosition::TuplePattern { .. } 3528 | ErlangSourceBuilderPosition::BitArray { .. } 3529 | ErlangSourceBuilderPosition::Map { .. } 3530 | ErlangSourceBuilderPosition::Block { .. } 3531 | ErlangSourceBuilderPosition::ClauseGuard 3532 | ErlangSourceBuilderPosition::UnaryOperator 3533 | ErlangSourceBuilderPosition::FunctionType { 3534 expected: 3535 ExpectedFunctionTypeItem::Arguments { .. } | ExpectedFunctionTypeItem::ReturnType, 3536 .. 3537 } 3538 | ErlangSourceBuilderPosition::TypeSpec { 3539 expected: TypeSpecExpectedItem::TypeDefinition, 3540 } 3541 | ErlangSourceBuilderPosition::MapField { 3542 expected: MapFieldExpectedItem::Key | MapFieldExpectedItem::Value, 3543 } 3544 | ErlangSourceBuilderPosition::List { 3545 expected: ExpectedListItem::First | ExpectedListItem::Rest, 3546 .. 3547 } 3548 | ErlangSourceBuilderPosition::BitArraySegment { 3549 expected: 3550 BitArraySegmentExpectedItem::Size 3551 | BitArraySegmentExpectedItem::Specifiers 3552 | BitArraySegmentExpectedItem::Value { .. }, 3553 .. 3554 } 3555 | ErlangSourceBuilderPosition::FunctionCall { 3556 expected: ExpectedCallItem::Arguments { .. } | ExpectedCallItem::FunctionToBeCalled, 3557 .. 3558 } 3559 | ErlangSourceBuilderPosition::MatchPattern { 3560 expected: ExpectedMatchPatternSide::Left | ExpectedMatchPatternSide::Right, 3561 } 3562 | ErlangSourceBuilderPosition::Case { 3563 expected: ExpectedCaseItem::Subject | ExpectedCaseItem::Branches { .. }, 3564 } 3565 | ErlangSourceBuilderPosition::CaseClause { 3566 expected: 3567 ExpectedCaseClauseItem::Pattern 3568 | ExpectedCaseClauseItem::Guards { .. } 3569 | ExpectedCaseClauseItem::Body { .. }, 3570 } 3571 | ErlangSourceBuilderPosition::BinaryOperator { 3572 expected: ExpectedBinaryOperatorSide::Left | ExpectedBinaryOperatorSide::Right, 3573 .. 3574 } 3575 | ErlangSourceBuilderPosition::RecordAttribute { .. } 3576 | ErlangSourceBuilderPosition::MatchOperator { 3577 expected: ExpectedMatchSide::Expression | ExpectedMatchSide::Pattern, 3578 } 3579 | ErlangSourceBuilderPosition::RecordField { .. } => (), 3580 } 3581 } 3582 3583 fn new_record_field(&mut self) { 3584 self.pop_leftover_items(); 3585 let Some(ErlangSourceBuilderPosition::RecordAttribute { first }) = self.position.last_mut() 3586 else { 3587 panic!("tried generating record field outside of record attribute"); 3588 }; 3589 3590 if *first { 3591 *first = false; 3592 } else { 3593 self.code.push(','); 3594 } 3595 self.code.push('\n'); 3596 self.push_indentation(); 3597 } 3598 3599 fn push_indentation(&mut self) { 3600 for _ in 0..self.indentation { 3601 self.code.push(' '); 3602 } 3603 } 3604 3605 /// This produces a pretty printed error message including the current 3606 /// position. 3607 fn error_with_position(&self, expected: &str) -> String { 3608 let position = self.position.last(); 3609 format!("tried {expected}, position: {position:?}") 3610 } 3611 3612 fn doc_content(&mut self, content: DocContent<'_>) { 3613 match content { 3614 DocContent::False => self.code.push_str("false"), 3615 // Escaping strings generated inside doc attributes is a little 3616 // different: since their content doesn't come from a Gleam 3617 // literal string but freeform text, their content might contain 3618 // all sorts of unescaped characters. 3619 DocContent::String(content) => { 3620 self.code.push_str("~\""); 3621 self.code 3622 .push_str(&content.replace("\\", "\\\\").replace("\"", "\\\"")); 3623 self.code.push('"'); 3624 } 3625 } 3626 } 3627} 3628 3629/// This wraps an atom name in between single quotes if needed. 3630fn quote_atom_name(name: &str) -> String { 3631 if is_erlang_reserved_word(name) { 3632 // Escape because of keyword collision 3633 format!("'{name}'") 3634 } else if atom_name_regex().is_match(name) { 3635 String::from(name) 3636 } else { 3637 // Escape because of characters contained 3638 format!("'{name}'") 3639 } 3640} 3641 3642static ATOM_NAME_REGEX: OnceLock<Regex> = OnceLock::new(); 3643 3644fn atom_name_regex() -> &'static Regex { 3645 ATOM_NAME_REGEX.get_or_init(|| Regex::new(r"^[a-z][a-z0-9_@]*$").expect("atom RE regex")) 3646} 3647 3648fn is_erlang_reserved_word(name: &str) -> bool { 3649 matches!( 3650 name, 3651 "!" | "receive" 3652 | "bnot" 3653 | "div" 3654 | "rem" 3655 | "band" 3656 | "bor" 3657 | "bxor" 3658 | "bsl" 3659 | "bsr" 3660 | "not" 3661 | "and" 3662 | "or" 3663 | "xor" 3664 | "orelse" 3665 | "andalso" 3666 | "when" 3667 | "end" 3668 | "fun" 3669 | "try" 3670 | "catch" 3671 | "after" 3672 | "begin" 3673 | "let" 3674 | "query" 3675 | "cond" 3676 | "if" 3677 | "of" 3678 | "case" 3679 | "maybe" 3680 | "else" 3681 ) 3682}