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