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