diff --git a/compiler-core/src/erlang.rs b/compiler-core/src/erlang.rs index e82062aeb..2c8b366f3 100644 --- a/compiler-core/src/erlang.rs +++ b/compiler-core/src/erlang.rs @@ -32,12 +32,12 @@ use std::{collections::HashMap, ops::Deref, sync::Arc}; /// This is an open runtime error to which more fields can still be added. #[must_use] -struct RuntimeError { +struct RuntimeError { /// This is the map that is going to be thrown by the `erlang:error` call. - error_map: erlang_generation::Map, + error_map: Map, /// This is the call to `erlang:error` that will throw the error, with the /// map as an argument. - erlang_error_call: erlang_generation::Call, + erlang_error_call: Call, } /// Represents all the different kind of runtime errors that Gleam can raise. @@ -154,7 +154,7 @@ struct FunctionGenerator<'a, 'generator> { /// variable_names: im::HashMap, - /// This keeps track of the number of throwaway variables that have already + /// This keeps track of the number of generated variables that have already /// been generated in the current function. /// For example if this is `2` it means we've already generated: /// @@ -164,10 +164,10 @@ struct FunctionGenerator<'a, 'generator> { /// _value@2 /// ``` /// - /// We need this to make sure that every time we generate a new throwaway + /// We need this to make sure that every time we generate a new generated /// variable it has a unique name not shadowing anything else. /// - throwaway_variables: usize, + generated_variables: usize, /// This keeps track of all the names that are taken for the current /// function and can't be used when defining new variables. @@ -488,7 +488,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { module_generator, taken_names: im::HashMap::new(), variable_names: im::HashMap::new(), - throwaway_variables: 0, + generated_variables: 0, } } @@ -562,13 +562,13 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { /// The generated name is guaranteed to always be unique for the given /// function. /// - fn new_throwaway_variable(&mut self) -> EcoString { - let name = if self.throwaway_variables == 0 { + fn new_generated_variable(&mut self) -> EcoString { + let name = if self.generated_variables == 0 { EcoString::from("_value") } else { - eco_format!("_value@{}", self.throwaway_variables) + eco_format!("_value@{}", self.generated_variables) }; - self.throwaway_variables += 1; + self.generated_variables += 1; name } @@ -732,7 +732,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // If an argument is made of just underscores, then that would result // in a syntax error in the generated Erlang, where the external // function is called with a discard `io:format(_, _)`! - // So in this case we use a throwaway name to make sure the external + // So in this case we use a generated name to make sure the external // function can be called correctly. ArgNames::Discard { name, location } | ArgNames::LabelledDiscard { @@ -741,7 +741,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { .. } if is_external => { if name.chars().all(|char| char == '_') { - self.new_throwaway_variable() + self.new_generated_variable() } else { self.new_erlang_variable(name, *location) } @@ -764,8 +764,8 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // We go over each statement one by one and produce the code they need. for i in 0..statements.len() { match statements.get(i).expect("statement in range") { - Statement::Expression(expression) => self.expr(builder, expression), - Statement::Use(use_) => self.expr(builder, &use_.call), + Statement::Expression(expression) => self.expression(builder, expression), + Statement::Use(use_) => self.expression(builder, &use_.call), Statement::Assert(assert) => self.assert(builder, assert), Statement::Assignment(assignment) => match &assignment.kind { AssignmentKind::Let | AssignmentKind::Generated => { @@ -812,7 +812,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { } } - fn expr( + fn expression( &mut self, builder: &mut impl ErlangBuilder, expression: &'a TypedExpr, @@ -858,7 +858,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { left, right, .. - } => self.bin_op(builder, operator, left, right), + } => self.binary_operator(builder, operator, left, right), // // BitArrays, Lists, and Tuples. @@ -1091,14 +1091,14 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { /// After you're done generating those additional fields remember you _must_ /// call `end_runtime_error` before generating any other piece of code! /// - fn start_runtime_error( + fn start_runtime_error>( &mut self, - builder: &mut impl ErlangBuilder, + builder: &mut Builder, error_kind: RuntimeErrorKind, location: SrcSpan, message: Option<&'a TypedExpr>, - ) -> RuntimeError { - let call = builder.start_remote_call(ErlangModuleName::new("erlang"), "error"); + ) -> RuntimeError { + let call = builder.start_remote_call(ErlangModuleName::erlang(), "error"); let map = builder.start_map(); builder.map_field(); @@ -1146,10 +1146,10 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { } /// This closes an open runtime error. - fn end_runtime_error( + fn end_runtime_error>( &self, - builder: &mut impl ErlangBuilder, - runtime_error: RuntimeError, + builder: &mut Builder, + runtime_error: RuntimeError, ) { builder.end_map(runtime_error.error_map); builder.end_call(runtime_error.erlang_error_call); @@ -1162,10 +1162,10 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { ) { if needs_begin_end_wrapping(expression) { let block = builder.start_block(); - self.expr(builder, expression); + self.expression(builder, expression); builder.end_block(block); } else { - self.expr(builder, expression); + self.expression(builder, expression); } } @@ -1232,7 +1232,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // end // ``` let clause = builder.start_case_clause(); - let matched_value_name = self.new_throwaway_variable(); + let matched_value_name = self.new_generated_variable(); builder.match_pattern(); let mut generator = PatternGenerator::new(self); generator.pattern(builder, pattern); @@ -1246,7 +1246,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // This is the catch all branch to throw an error otherwise. let clause = builder.start_case_clause(); - let value_name = self.new_throwaway_variable(); + let value_name = self.new_generated_variable(); builder.variable_pattern(&value_name); let clause = builder.end_clause_pattern(clause); let clause = builder.end_clause_guards(clause); @@ -1355,7 +1355,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { }, ) } else { - self.expr(builder, finally) + self.expression(builder, finally) } } @@ -1413,24 +1413,24 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { }; // If the left or right hand side are not simple variables we'll - // need to first assign those to throwaway variables and keep + // need to first assign those to generated variables and keep // track of those names. let left = if !left.is_var() { - let name = self.new_throwaway_variable(); + let name = self.new_generated_variable(); builder.match_operator(); builder.variable_pattern(&name); self.maybe_block_expr(builder, left); - AssertionExpression::from_throwaway_variable(name, left) + AssertionExpression::from_generated_variable(name, left) } else { AssertionExpression::from_expression(left) }; let right = if !right.is_var() { - let name = self.new_throwaway_variable(); + let name = self.new_generated_variable(); builder.match_operator(); builder.variable_pattern(&name); self.maybe_block_expr(builder, right); - AssertionExpression::from_throwaway_variable(name, right) + AssertionExpression::from_generated_variable(name, right) } else { AssertionExpression::from_expression(right) }; @@ -1479,11 +1479,11 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { let mut call_arguments = Vec::with_capacity(arguments.len()); for argument in arguments { let argument = if !argument.value.is_var() { - let name = self.new_throwaway_variable(); + let name = self.new_generated_variable(); builder.match_operator(); builder.variable_pattern(&name); self.maybe_block_expr(builder, &argument.value); - AssertionExpression::from_throwaway_variable(name, &argument.value) + AssertionExpression::from_generated_variable(name, &argument.value) } else { AssertionExpression::from_expression(&argument.value) }; @@ -1904,7 +1904,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { tuple: &'a TypedExpr, index: u64, ) { - let call = builder.start_remote_call(ErlangModuleName::new("erlang"), "element"); + let call = builder.start_remote_call(ErlangModuleName::erlang(), "element"); builder.int((index + 1).into()); self.maybe_block_expr(builder, tuple); builder.end_call(call); @@ -2213,7 +2213,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { if let TypedExpr::Block { statements, .. } = &clause.then { self.statement_sequence(builder, statements); } else { - self.expr(builder, &clause.then); + self.expression(builder, &clause.then); } builder.end_clause_body(clause_body); } @@ -2487,7 +2487,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { }); } - fn bin_op( + fn binary_operator( &mut self, builder: &mut impl ErlangBuilder, name: &'a BinOp, @@ -2548,7 +2548,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // We first have to evaluate the left hand side, and store its // result in a variable to use later. let left_name = if !is_left_hand_side_pure { - let left_name = self.new_throwaway_variable(); + let left_name = self.new_generated_variable(); builder.match_operator(); builder.variable_pattern(&left_name); self.maybe_block_expr(builder, left); @@ -2577,7 +2577,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { builder.end_clause_body(body); // _value -> left / _value - let denominator = self.new_throwaway_variable(); + let denominator = self.new_generated_variable(); let clause = builder.start_case_clause(); builder.variable_pattern(&denominator); let guards = builder.end_clause_pattern(clause); @@ -2624,7 +2624,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { } => { // If the left hand side is not a pure expression we will have // to evaluate it before the right hand side of the expression. - // So we assign it to a throwaway variable that we will then + // So we assign it to a generated variable that we will then // reference in the case expression's body. // It will look something like this: // @@ -2637,7 +2637,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // ``` // let left_name = if !is_left_hand_side_pure { - let left_name = self.new_throwaway_variable(); + let left_name = self.new_generated_variable(); builder.match_operator(); builder.variable_pattern(&left_name); self.maybe_block_expr(builder, left); @@ -2658,7 +2658,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { builder.end_clause_body(body); // _value -> left div _value - let denominator = self.new_throwaway_variable(); + let denominator = self.new_generated_variable(); let clause = builder.start_case_clause(); builder.variable_pattern(&denominator); let guards = builder.end_clause_pattern(clause); @@ -2763,7 +2763,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { // unicode:characters_to_binary(, utf8, {utf16, big}) // ``` let call = - builder.start_remote_call(ErlangModuleName::new("unicode"), "characters_to_binary"); + builder.start_remote_call(ErlangModuleName::unicode(), "characters_to_binary"); { self.maybe_block_expr(builder, &segment.value); builder.atom("utf8"); @@ -2814,7 +2814,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { builder.int(int_value.clone()); } } else { - let call = builder.start_remote_call(ErlangModuleName::new("erlang"), "max"); + let call = builder.start_remote_call(ErlangModuleName::erlang(), "max"); builder.int(BigInt::ZERO); self.maybe_block_expr(builder, size); builder.end_call(call); @@ -2916,7 +2916,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { tuple: &'a TypedClauseGuard, index: u64, ) { - let call = builder.start_remote_call(ErlangModuleName::new("erlang"), "element"); + let call = builder.start_remote_call(ErlangModuleName::erlang(), "element"); builder.int((index + 1).into()); self.clause_guard(builder, tuple, &HashMap::new()); builder.end_call(call); @@ -2989,7 +2989,7 @@ impl<'a, 'generator> FunctionGenerator<'a, 'generator> { arguments: usize, ) { let arguments = (0..arguments) - .map(|_| self.new_throwaway_variable()) + .map(|_| self.new_generated_variable()) .collect_vec(); let function = builder.start_anonymous_function(&arguments); @@ -3265,7 +3265,7 @@ fn how_to_divide(left: &TypedExpr, right: &TypedExpr) -> HowToDivide { pub fn record_definition(record_name: &str, fields: &[(&str, Arc)]) -> String { let mut builder = ErlangSourceBuilder::new(None); - let record = builder.start_record_attribute(&to_snake_case(record_name)); + builder.start_record_attribute(&to_snake_case(record_name)); let type_printer = TypeGenerator::new("").var_as_any(); for (field_name, field_type) in fields { @@ -3274,7 +3274,7 @@ pub fn record_definition(record_name: &str, fields: &[(&str, Arc)]) -> Str type_printer.type_(&mut builder, field_type); } - builder.end_record_attribute(record); + builder.end_record_attribute(()); builder.into_output() } @@ -3563,7 +3563,7 @@ impl<'a> AssertionExpression<'a> { self } - fn from_throwaway_variable(name: EcoString, original_expression: &'a TypedExpr) -> Self { + fn from_generated_variable(name: EcoString, original_expression: &'a TypedExpr) -> Self { Self { runtime_value: Some(AssertedExpressionRuntimeValue::Variable(name)), kind: if original_expression.is_literal() { @@ -3628,7 +3628,7 @@ enum AssertedExpressionRuntimeValue<'a> { /// That's because we know wether the assertion failed (it must be false), /// or not (it must be true). KnownBool(bool), - /// The asserted value was bound to a throwaway variable with the given + /// The asserted value was bound to a generated variable with the given /// name, and we can reference it using that name. Variable(EcoString), /// The asserted value is an expression we need to inline in the error. diff --git a/compiler-core/src/erlang/pattern.rs b/compiler-core/src/erlang/pattern.rs index 07aab11fe..37f003f76 100644 --- a/compiler-core/src/erlang/pattern.rs +++ b/compiler-core/src/erlang/pattern.rs @@ -415,7 +415,7 @@ impl<'a, 'generator, 'module> PatternGenerator<'a, 'generator, 'module> { builder.end_clause_body(clause); let clause = builder.start_case_clause(); - let denominator = self.generator.new_throwaway_variable(); + let denominator = self.generator.new_generated_variable(); builder.variable_pattern(&denominator); let clause = builder.end_clause_pattern(clause); let clause = builder.end_clause_guards(clause); diff --git a/erlang-generation/src/lib.rs b/erlang-generation/src/lib.rs index 593a76102..efa00d2f7 100644 --- a/erlang-generation/src/lib.rs +++ b/erlang-generation/src/lib.rs @@ -35,95 +35,17 @@ impl ErlangModuleName { pub fn new(gleam_module_name: &str) -> Self { Self(gleam_module_name.replace("/", "@").into()) } -} -#[must_use] -/// Represents an open function that has yet to be closed. -/// A function definition is started with `ErlangBuilder::start_function` and -/// _must_ be closed using `ErlangBuilder::end_function`. -pub struct Function {} - -#[must_use] -/// Represents an open function call that has yet to be closed. -pub struct Call {} - -#[must_use] -/// Represents an open case expression that has yet to be closed. -pub struct Case {} - -#[must_use] -/// Represents an open case clause pattern that has yet to be generated. -pub struct ClausePattern {} - -#[must_use] -/// Represents a set of clause guards that has yet to be closed. -pub struct ClauseGuards {} - -#[must_use] -/// Represents an open clause body that has yet to be closed. -pub struct ClauseBody {} - -#[must_use] -/// Represents an open tuple that has yet to be closed. -pub struct Tuple {} - -#[must_use] -/// Represents an open map that has yet to be closed. -pub struct Map {} - -#[must_use] -/// Represents an open bit array that has yet to be closed. -pub struct BitArray {} - -#[must_use] -/// Represents an open bit array pattern that has yet to be closed. -pub struct BitArrayPattern {} - -#[must_use] -/// Represents an open tuple type that has yet to be closed. -pub struct TupleType {} - -#[must_use] -/// Represents an open tuple pattern that has yet to be closed. -pub struct TuplePattern {} - -#[must_use] -/// Represents an open doc/moduledoc attribute. -pub struct DocAttribute {} - -#[must_use] -/// Represents an open record attribute. -pub struct RecordAttribute {} - -#[must_use] -/// Represents an open function type annotation that has yet to be closed after -/// generating the arguments types and the return type. -pub struct FunctionType {} - -#[must_use] -/// Represents an open named type that has yet to be closed after generating -/// the types it takes as an argument (if any). -pub struct NamedType {} - -#[must_use] -/// Represents an open alternative type that has yet to be closed after -/// generating all of its alternatives. -pub struct UnionType {} - -#[must_use] -/// Represents an open function type annotation that has yet to be closed after -/// generating the arguments types and the return type. -pub struct FunctionSpec {} - -#[must_use] -/// Represents an open block that has yet to be closed after generating the -/// statements that go inside it. -pub struct Block {} - -#[must_use] -/// Represents an open list of arguments' types in a function type annotation -/// that has yet to be closed. -pub struct FunctionTypeArguments {} + /// The Erlang/OTP `erlang` module. + pub fn erlang() -> Self { + Self("erlang".into()) + } + + /// The Erlang/OTP `unicode` module. + pub fn unicode() -> Self { + Self("unicode".into()) + } +} /// All the possible specifiers that can be used in a bit array segment. pub enum BitArraySegmentSpecifier { @@ -157,6 +79,74 @@ pub enum BitArraySegmentSpecifier { /// https://www.erlang.org/doc/apps/erts/absform.html /// pub trait ErlangBuilder { + /// Represents an open function that has yet to be closed. + /// A function definition is started with `ErlangBuilder::start_function` and + /// _must_ be closed using `ErlangBuilder::end_function`. + type Function; + + /// Represents an open function call that has yet to be closed. + type Call; + + /// Represents an open case expression that has yet to be closed. + type Case; + + /// Represents an open case clause pattern that has yet to be generated. + type ClausePattern; + + /// Represents a set of clause guards that has yet to be closed. + type ClauseGuards; + + /// Represents an open clause body that has yet to be closed. + type ClauseBody; + + /// Represents an open tuple that has yet to be closed. + type Tuple; + + /// Represents an open map that has yet to be closed. + type Map; + + /// Represents an open bit array that has yet to be closed. + type BitArray; + + /// Represents an open bit array pattern that has yet to be closed. + type BitArrayPattern; + + /// Represents an open tuple type that has yet to be closed. + type TupleType; + + /// Represents an open tuple pattern that has yet to be closed. + type TuplePattern; + + /// Represents an open doc/moduledoc attribute. + type DocAttribute; + + /// Represents an open record attribute. + type RecordAttribute; + + /// Represents an open function type annotation that has yet to be closed after + /// generating the arguments types and the return type. + type FunctionType; + + /// Represents an open named type that has yet to be closed after generating + /// the types it takes as an argument (if any). + type NamedType; + + /// Represents an open alternative type that has yet to be closed after + /// generating all of its alternatives. + type UnionType; + + /// Represents an open function type annotation that has yet to be closed after + /// generating the arguments types and the return type. + type FunctionSpec; + + /// Represents an open block that has yet to be closed after generating the + /// statements that go inside it. + type Block; + + /// Represents an open list of arguments' types in a function type annotation + /// that has yet to be closed. + type FunctionTypeArguments; + /// Creates a new `ErlangBuilder` data structure to generate Erlang code. /// If a module name is provided this will also automatically take care of /// generating the appropriate `-module` annotation at the very beginning. @@ -230,7 +220,7 @@ pub trait ErlangBuilder { /// -doc(false). /// ``` /// - fn start_doc_attribute(&mut self) -> DocAttribute; + fn start_doc_attribute(&mut self) -> Self::DocAttribute; /// Starts a `-moduledoc` attribute. /// What is generated after calling this function will end up inside the @@ -251,12 +241,12 @@ pub trait ErlangBuilder { /// -moduledoc(false). /// ``` /// - fn start_moduledoc_attribute(&mut self) -> DocAttribute; + fn start_moduledoc_attribute(&mut self) -> Self::DocAttribute; /// This closes the currently open doc/moduledoc attribute. /// Code generated after this is not gonna be part of it. /// - fn end_doc_attribute(&mut self, attribute: DocAttribute); + fn end_doc_attribute(&mut self, attribute: Self::DocAttribute); /// This generates the code for a `-compile([]).` attribute where all the /// strings produces by the given iterator are going to be passed as atom @@ -311,12 +301,12 @@ pub trait ErlangBuilder { /// -record(wobble, { wibble :: ok }). /// ``` /// - fn start_record_attribute(&mut self, record_name: &str) -> RecordAttribute; + fn start_record_attribute(&mut self, record_name: &str) -> Self::RecordAttribute; /// This closes the currently open record attribute. /// Code generated after this is not gonna be part of it. /// - fn end_record_attribute(&mut self, record: RecordAttribute); + fn end_record_attribute(&mut self, record: Self::RecordAttribute); /// This creates a record field inside a record attribute. /// After this you're supposed to generate two things: @@ -351,12 +341,12 @@ pub trait ErlangBuilder { /// -spec wibble(integer(), A) -> A. /// ``` /// - fn start_function_spec(&mut self, name: &str, arity: usize) -> FunctionSpec; + fn start_function_spec(&mut self, name: &str, arity: usize) -> Self::FunctionSpec; /// This closes the currently open function spec. /// Code generated after this is not gonna be part of this function spec. /// - fn end_function_spec(&mut self, function_spec: FunctionSpec); + fn end_function_spec(&mut self, function_spec: Self::FunctionSpec); /// This starts an Erlang type spec. /// After this call you're expected to generate a single type; that's going @@ -413,7 +403,7 @@ pub trait ErlangBuilder { /// (integer(), A) -> A. /// ``` /// - fn start_function_type(&mut self) -> FunctionTypeArguments; + fn start_function_type(&mut self) -> Self::FunctionTypeArguments; /// This closes the currently open function type arguments list. /// This means that the next type that is generated is going to be the @@ -422,13 +412,15 @@ pub trait ErlangBuilder { /// After that you must call `end_function_type` to close the function /// type. /// - fn end_function_type_arguments(&mut self, function_type: FunctionTypeArguments) - -> FunctionType; + fn end_function_type_arguments( + &mut self, + function_type: Self::FunctionTypeArguments, + ) -> Self::FunctionType; /// This takes a function type and closes it. /// Code generated after this is not gonna be part of this function type. /// - fn end_function_type(&mut self, function_type: FunctionType); + fn end_function_type(&mut self, function_type: Self::FunctionType); /// This starts a named type (either defined previously in this module, or /// a built-in Erlang type) with the given name. @@ -448,7 +440,7 @@ pub trait ErlangBuilder { /// wibble(). /// ``` /// - fn start_named_type(&mut self, name: &str) -> NamedType; + fn start_named_type(&mut self, name: &str) -> Self::NamedType; /// This starts a remote named type with the given module and name. /// Any code generated after this is gonna be an argument of the open @@ -467,12 +459,12 @@ pub trait ErlangBuilder { /// wibble:wobble(). /// ``` /// - fn start_remote_named_type(&mut self, module: ErlangModuleName, name: &str) -> NamedType; + fn start_remote_named_type(&mut self, module: ErlangModuleName, name: &str) -> Self::NamedType; /// This takes a named type and closes it. /// Code generated after this is not gonna be part of this named type. /// - fn end_named_type(&mut self, named_type: NamedType); + fn end_named_type(&mut self, named_type: Self::NamedType); /// This starts a tuple type. /// Any code generated after this is gonna be one of the tuple items. @@ -492,12 +484,12 @@ pub trait ErlangBuilder { /// {nil, ok}. /// ``` /// - fn start_tuple_type(&mut self) -> TupleType; + fn start_tuple_type(&mut self) -> Self::TupleType; /// This takes a tuple type and closes it. /// Code generated after this is not gonna be part of this tuple type. /// - fn end_tuple_type(&mut self, tuple: TupleType); + fn end_tuple_type(&mut self, tuple: Self::TupleType); /// This starts a union type. /// Any code generated after this is gonna be a possible alternative of this @@ -518,12 +510,12 @@ pub trait ErlangBuilder { /// ok | error. /// ``` /// - fn start_union_type(&mut self) -> UnionType; + fn start_union_type(&mut self) -> Self::UnionType; /// This takes a union type and closes it. /// Code generated after this is not gonna be part of this union type. /// - fn end_union_type(&mut self, union_type: UnionType); + fn end_union_type(&mut self, union_type: Self::UnionType); /// This generated the code for a type variable with the given name. /// @@ -591,7 +583,7 @@ pub trait ErlangBuilder { name: &str, arity: usize, arguments_names: impl IntoIterator, - ) -> Function; + ) -> Self::Function; /// This starts an expression defining an anonymous function. /// Any code generated after this is gonna be a statement inside the @@ -614,12 +606,12 @@ pub trait ErlangBuilder { fn start_anonymous_function>( &mut self, arguments_names: impl IntoIterator, - ) -> Function; + ) -> Self::Function; /// This takes a function and closes it. /// Code generated after this is not gonna be part of this function. /// - fn end_function(&mut self, function: Function); + fn end_function(&mut self, function: Self::Function); /// This starts a block expression. /// Any code generated after this is gonna be a statement inside the open @@ -643,12 +635,12 @@ pub trait ErlangBuilder { /// end. /// ``` /// - fn start_block(&mut self) -> Block; + fn start_block(&mut self) -> Self::Block; /// This takes a block and closes it. /// Code generated after this is not gonna be part of this block. /// - fn end_block(&mut self, block: Block); + fn end_block(&mut self, block: Self::Block); /// This starts a remote call. /// Any code generated after this is gonna be an argument of the open @@ -668,7 +660,7 @@ pub trait ErlangBuilder { /// io:format(~"Giacomo"). /// ``` /// - fn start_remote_call(&mut self, module: ErlangModuleName, function: &str) -> Call; + fn start_remote_call(&mut self, module: ErlangModuleName, function: &str) -> Self::Call; /// This starts a function call. /// The expression generated immediately after this is going to be the thing @@ -690,12 +682,12 @@ pub trait ErlangBuilder { /// wibble(~"Hello", ~"Giacomo"). /// ``` /// - fn start_call(&mut self) -> Call; + fn start_call(&mut self) -> Self::Call; /// This takes an open call and closes it. /// Code generated after this is not gonna be an argument to this call. /// - fn end_call(&mut self, call: Call); + fn end_call(&mut self, call: Self::Call); /// This starts a tuple. /// Any code generated after this is gonna be an item of the tuple. @@ -715,12 +707,12 @@ pub trait ErlangBuilder { /// {~"Hello", 1}. /// ``` /// - fn start_tuple(&mut self) -> Tuple; + fn start_tuple(&mut self) -> Self::Tuple; /// This takes an open tuple and closes it. /// Code generated after this is not gonna be an item of the tuple. /// - fn end_tuple(&mut self, tuple: Tuple); + fn end_tuple(&mut self, tuple: Self::Tuple); /// This starts an Erlang map. /// After this call you can add fields to the map using the `map_field` @@ -749,12 +741,12 @@ pub trait ErlangBuilder { /// }. /// ``` /// - fn start_map(&mut self) -> Map; + fn start_map(&mut self) -> Self::Map; /// This takes an open map and closes it. /// Code generated after this is not gonna be a map field. /// - fn end_map(&mut self, map: Map); + fn end_map(&mut self, map: Self::Map); /// This is used to add new fields to an open map. /// After calling this you must generate exactly two values: the first one @@ -789,12 +781,12 @@ pub trait ErlangBuilder { /// <<1, ~"hello">>. /// ``` /// - fn start_bit_array(&mut self) -> BitArray; + fn start_bit_array(&mut self) -> Self::BitArray; /// This takes an open bit array and closes it. /// Code generated after this is not gonna be a segment of the bit array. /// - fn end_bit_array(&mut self, bit_array: BitArray); + fn end_bit_array(&mut self, bit_array: Self::BitArray); /// This starts a new bit array segment. Make sure to call it after /// `start_bit_array`! @@ -894,12 +886,12 @@ pub trait ErlangBuilder { /// end. /// ``` /// - fn start_case(&mut self) -> Case; + fn start_case(&mut self) -> Self::Case; /// This ends an open case expression. /// Any code generated after this is not going to be part of it. /// - fn end_case(&mut self, case: Case); + fn end_case(&mut self, case: Self::Case); /// This starts a new case clause inside a case expression. /// After this is called you must generate a single pattern and then call @@ -907,23 +899,23 @@ pub trait ErlangBuilder { /// /// For an example on how to generate a full case clause check the /// `start_case` documentation. - fn start_case_clause(&mut self) -> ClausePattern; + fn start_case_clause(&mut self) -> Self::ClausePattern; /// This ends the case clause's pattern. After this you must generate the /// clause guards and then call `end_clause_guards`. /// If the clause you're generating has no guards you can immediately call /// that function without generating anything inbetween. - fn end_clause_pattern(&mut self, clause_pattern: ClausePattern) -> ClauseGuards; + fn end_clause_pattern(&mut self, clause_pattern: Self::ClausePattern) -> Self::ClauseGuards; /// This ends the case clause's guards. Anything that is generated after /// this is going to be a statement inside the current case clause until /// `end_clause_body` is called. - fn end_clause_guards(&mut self, clause_guards: ClauseGuards) -> ClauseBody; + fn end_clause_guards(&mut self, clause_guards: Self::ClauseGuards) -> Self::ClauseBody; /// This takes an open clause body and ends it. /// After this you can start generating new case clauses, or end the /// currently open case expression if this was the last clause! - fn end_clause_body(&mut self, clause_body: ClauseBody); + fn end_clause_body(&mut self, clause_body: Self::ClauseBody); /// This creates a variable expression with the given name. /// For example: @@ -1118,11 +1110,11 @@ pub trait ErlangBuilder { /// {~"Hello", _}. /// ``` /// - fn start_tuple_pattern(&mut self) -> TuplePattern; + fn start_tuple_pattern(&mut self) -> Self::TuplePattern; /// This takes an open tuple pattern and closes it. /// Any code generated after this is not gonna be part of that pattern. - fn end_tuple_pattern(&mut self, tuple: TuplePattern); + fn end_tuple_pattern(&mut self, tuple: Self::TuplePattern); /// This starts an Erlang bitstring (that's a Gleam's BitArray) pattern. /// Any code generated after this is gonna be a segment of the pattern. @@ -1151,12 +1143,12 @@ pub trait ErlangBuilder { /// <<1, _>>. /// ``` /// - fn start_bit_array_pattern(&mut self) -> BitArrayPattern; + fn start_bit_array_pattern(&mut self) -> Self::BitArrayPattern; /// This takes an open bit array pattern and closes it. /// Code generated after this is not gonna be a segment of the bit array. /// - fn end_bit_array_pattern(&mut self, bit_array: BitArrayPattern); + fn end_bit_array_pattern(&mut self, bit_array: Self::BitArrayPattern); /// This creates a list pattern. /// The next two generated values are going to be respectively the pattern @@ -1691,6 +1683,27 @@ static UNICODE_ESCAPE_SEQUENCE_PATTERN: OnceLock = OnceLock::new(); /// require a bit of extra book-keeping in the `new_x` functions. /// impl ErlangBuilder for ErlangSourceBuilder { + type BitArray = (); + type BitArrayPattern = (); + type Block = (); + type Call = (); + type Case = (); + type ClauseBody = (); + type ClauseGuards = (); + type ClausePattern = (); + type DocAttribute = (); + type Function = (); + type FunctionSpec = (); + type FunctionType = (); + type FunctionTypeArguments = (); + type Map = (); + type NamedType = (); + type RecordAttribute = (); + type Tuple = (); + type TuplePattern = (); + type TupleType = (); + type UnionType = (); + fn new(module: Option) -> Self { Self { code: if let Some(module) = module { @@ -1765,23 +1778,21 @@ impl ErlangBuilder for ErlangSourceBuilder { self.code.push_str("]).\n"); } - fn start_doc_attribute(&mut self) -> DocAttribute { + fn start_doc_attribute(&mut self) -> Self::DocAttribute { self.new_top_level_form(); self.code.push_str("-doc("); self.position .push(ErlangSourceBuilderPosition::DocAttribute); - DocAttribute {} } - fn start_moduledoc_attribute(&mut self) -> DocAttribute { + fn start_moduledoc_attribute(&mut self) -> Self::DocAttribute { self.new_top_level_form(); self.code.push_str("-moduledoc("); self.position .push(ErlangSourceBuilderPosition::DocAttribute); - DocAttribute {} } - fn end_doc_attribute(&mut self, _attribute: DocAttribute) { + fn end_doc_attribute(&mut self, _attribute: Self::DocAttribute) { self.close_currently_open_item(); } @@ -1812,7 +1823,7 @@ impl ErlangBuilder for ErlangSourceBuilder { self.code.push_str(")."); } - fn start_record_attribute(&mut self, record_name: &str) -> RecordAttribute { + fn start_record_attribute(&mut self, record_name: &str) -> Self::RecordAttribute { self.new_top_level_form(); self.code.push_str("-record("); self.code.push_str("e_atom_name(record_name)); @@ -1820,11 +1831,9 @@ impl ErlangBuilder for ErlangSourceBuilder { self.indentation += INDENT; self.position .push(ErlangSourceBuilderPosition::RecordAttribute { first: true }); - - RecordAttribute {} } - fn end_record_attribute(&mut self, _record: RecordAttribute) { + fn end_record_attribute(&mut self, _record: Self::RecordAttribute) { self.close_currently_open_item(); } @@ -1836,16 +1845,15 @@ impl ErlangBuilder for ErlangSourceBuilder { }); } - fn start_function_spec(&mut self, name: &str, _arity: usize) -> FunctionSpec { + fn start_function_spec(&mut self, name: &str, _arity: usize) -> Self::FunctionSpec { self.new_top_level_form(); self.code.push_str("\n-spec "); self.code.push_str("e_atom_name(name)); self.position .push(ErlangSourceBuilderPosition::FunctionSpec); - FunctionSpec {} } - fn end_function_spec(&mut self, _function_spec: FunctionSpec) { + fn end_function_spec(&mut self, _function_spec: Self::FunctionSpec) { self.close_currently_open_item(); } @@ -1877,7 +1885,7 @@ impl ErlangBuilder for ErlangSourceBuilder { }); } - fn start_function_type(&mut self) -> FunctionTypeArguments { + fn start_function_type(&mut self) -> Self::FunctionTypeArguments { self.new_type(); let needs_wrapping = @@ -1894,34 +1902,28 @@ impl ErlangBuilder for ErlangSourceBuilder { expected: ExpectedFunctionTypeItem::Arguments { first: true }, needs_wrapping, }); - - FunctionTypeArguments {} } fn end_function_type_arguments( &mut self, - _function_type: FunctionTypeArguments, - ) -> FunctionType { + _function_type: Self::FunctionTypeArguments, + ) -> Self::FunctionType { self.close_currently_open_item(); - - FunctionType {} } - fn end_function_type(&mut self, _function_type: FunctionType) { + fn end_function_type(&mut self, _function_type: Self::FunctionType) { self.close_currently_open_item(); } - fn start_named_type(&mut self, name: &str) -> NamedType { + fn start_named_type(&mut self, name: &str) -> Self::NamedType { self.new_type(); self.position .push(ErlangSourceBuilderPosition::NamedType { first: true }); self.code.push_str("e_atom_name(name)); self.code.push('('); - - NamedType {} } - fn start_remote_named_type(&mut self, module: ErlangModuleName, name: &str) -> NamedType { + fn start_remote_named_type(&mut self, module: ErlangModuleName, name: &str) -> Self::NamedType { self.new_type(); self.position .push(ErlangSourceBuilderPosition::NamedType { first: true }); @@ -1929,36 +1931,30 @@ impl ErlangBuilder for ErlangSourceBuilder { self.code.push(':'); self.code.push_str("e_atom_name(name)); self.code.push('('); - - NamedType {} } - fn end_named_type(&mut self, _named_type: NamedType) { + fn end_named_type(&mut self, _named_type: Self::NamedType) { self.close_currently_open_item(); } - fn start_tuple_type(&mut self) -> TupleType { + fn start_tuple_type(&mut self) -> Self::TupleType { self.new_type(); self.position .push(ErlangSourceBuilderPosition::TupleType { first: true }); self.code.push('{'); - - TupleType {} } - fn end_tuple_type(&mut self, _tuple: TupleType) { + fn end_tuple_type(&mut self, _tuple: Self::TupleType) { self.close_currently_open_item(); } - fn start_union_type(&mut self) -> UnionType { + fn start_union_type(&mut self) -> Self::UnionType { self.new_type(); self.position .push(ErlangSourceBuilderPosition::UnionType { first: true }); - - UnionType {} } - fn end_union_type(&mut self, _union_type: UnionType) { + fn end_union_type(&mut self, _union_type: Self::UnionType) { self.close_currently_open_item(); } @@ -1977,7 +1973,7 @@ impl ErlangBuilder for ErlangSourceBuilder { name: &str, _arity: usize, arguments_names: impl IntoIterator, - ) -> Function { + ) -> Self::Function { self.new_top_level_form(); self.code.push_str("e_atom_name(name)); self.code.push('('); @@ -1996,14 +1992,12 @@ impl ErlangBuilder for ErlangSourceBuilder { self.indentation += INDENT; self.position .push(ErlangSourceBuilderPosition::FunctionStatement { first: true }); - - Function {} } fn start_anonymous_function>( &mut self, arguments_names: impl IntoIterator, - ) -> Function { + ) -> Self::Function { self.new_expression(); self.code.push_str("fun("); @@ -2021,29 +2015,25 @@ impl ErlangBuilder for ErlangSourceBuilder { self.indentation += INDENT; self.position .push(ErlangSourceBuilderPosition::AnonymousFunctionStatement { first: true }); - - Function {} } - fn end_function(&mut self, _function: Function) { + fn end_function(&mut self, _function: Self::Function) { self.close_currently_open_item(); } - fn start_block(&mut self) -> Block { + fn start_block(&mut self) -> Self::Block { self.new_expression(); self.code.push_str("begin"); self.indentation += INDENT; self.position .push(ErlangSourceBuilderPosition::Block { first: true }); - - Block {} } - fn end_block(&mut self, _block: Block) { + fn end_block(&mut self, _block: Self::Block) { self.close_currently_open_item(); } - fn start_remote_call(&mut self, module: ErlangModuleName, function: &str) -> Call { + fn start_remote_call(&mut self, module: ErlangModuleName, function: &str) -> Self::Call { self.pop_leftover_items(); // If this function call we're generating is itself being called then @@ -2067,10 +2057,9 @@ impl ErlangBuilder for ErlangSourceBuilder { expected: ExpectedCallItem::Arguments { first: true }, called_item_needs_wrapping: false, }); - Call {} } - fn start_call(&mut self) -> Call { + fn start_call(&mut self) -> Self::Call { self.pop_leftover_items(); // If this function call we're generating is itself being called then @@ -2091,36 +2080,32 @@ impl ErlangBuilder for ErlangSourceBuilder { expected: ExpectedCallItem::FunctionToBeCalled, called_item_needs_wrapping: false, }); - Call {} } - fn end_call(&mut self, _call: Call) { + fn end_call(&mut self, _call: Self::Call) { self.close_currently_open_item(); } - fn start_tuple(&mut self) -> Tuple { + fn start_tuple(&mut self) -> Self::Tuple { self.new_expression(); self.code.push('{'); self.position .push(ErlangSourceBuilderPosition::Tuple { first: true }); - - Tuple {} } - fn end_tuple(&mut self, _tuple: Tuple) { + fn end_tuple(&mut self, _tuple: Self::Tuple) { self.close_currently_open_item(); } - fn start_map(&mut self) -> Map { + fn start_map(&mut self) -> Self::Map { self.new_expression(); self.code.push_str("#{"); self.indentation += INDENT; self.position .push(ErlangSourceBuilderPosition::Map { first: true }); - Map {} } - fn end_map(&mut self, _map: Map) { + fn end_map(&mut self, _map: Self::Map) { self.close_currently_open_item(); } @@ -2131,7 +2116,7 @@ impl ErlangBuilder for ErlangSourceBuilder { }); } - fn start_bit_array(&mut self) -> BitArray { + fn start_bit_array(&mut self) -> Self::BitArray { self.do_not_wrap_if_segment_value_or_size(); self.new_expression(); self.code.push_str("<<"); @@ -2139,11 +2124,9 @@ impl ErlangBuilder for ErlangSourceBuilder { kind: BitArrayKind::Expression, first: true, }); - - BitArray {} } - fn end_bit_array(&mut self, _bit_array: BitArray) { + fn end_bit_array(&mut self, _bit_array: Self::BitArray) { self.close_currently_open_item(); } @@ -2230,48 +2213,41 @@ impl ErlangBuilder for ErlangSourceBuilder { self.empty_list_of_kind(ListKind::Expression); } - fn start_case(&mut self) -> Case { + fn start_case(&mut self) -> Self::Case { self.new_expression(); self.code.push_str("case "); self.position.push(ErlangSourceBuilderPosition::Case { expected: ExpectedCaseItem::Subject, }); - - Case {} } - fn end_case(&mut self, _case: Case) { + fn end_case(&mut self, _case: Self::Case) { self.close_currently_open_item(); } - fn start_case_clause(&mut self) -> ClausePattern { + fn start_case_clause(&mut self) -> Self::ClausePattern { self.new_case_clause(); self.position.push(ErlangSourceBuilderPosition::CaseClause { expected: ExpectedCaseClauseItem::Pattern, }); - ClausePattern {} } - fn end_clause_pattern(&mut self, _clause_pattern: ClausePattern) -> ClauseGuards { + fn end_clause_pattern(&mut self, _clause_pattern: Self::ClausePattern) -> Self::ClauseGuards { self.close_currently_open_item(); self.position.push(ErlangSourceBuilderPosition::CaseClause { expected: ExpectedCaseClauseItem::Guards { first: true }, }); - - ClauseGuards {} } - fn end_clause_guards(&mut self, _clause_guards: ClauseGuards) -> ClauseBody { + fn end_clause_guards(&mut self, _clause_guards: Self::ClauseGuards) -> Self::ClauseBody { self.close_currently_open_item(); self.indentation += INDENT; self.position.push(ErlangSourceBuilderPosition::CaseClause { expected: ExpectedCaseClauseItem::Body { first: true }, }); - - ClauseBody {} } - fn end_clause_body(&mut self, _clause_body: ClauseBody) { + fn end_clause_body(&mut self, _clause_body: Self::ClauseBody) { self.close_currently_open_item(); } @@ -2376,30 +2352,27 @@ impl ErlangBuilder for ErlangSourceBuilder { self.code.push_str("e_atom_name(name)); } - fn start_tuple_pattern(&mut self) -> TuplePattern { + fn start_tuple_pattern(&mut self) -> Self::TuplePattern { self.new_pattern(); self.code.push('{'); self.position .push(ErlangSourceBuilderPosition::TuplePattern { first: true }); - TuplePattern {} } - fn end_tuple_pattern(&mut self, _tuple: TuplePattern) { + fn end_tuple_pattern(&mut self, _tuple: Self::TuplePattern) { self.close_currently_open_item(); } - fn start_bit_array_pattern(&mut self) -> BitArrayPattern { + fn start_bit_array_pattern(&mut self) -> Self::BitArrayPattern { self.new_pattern(); self.code.push_str("<<"); self.position.push(ErlangSourceBuilderPosition::BitArray { kind: BitArrayKind::Pattern, first: true, }); - - BitArrayPattern {} } - fn end_bit_array_pattern(&mut self, _bit_array: BitArrayPattern) { + fn end_bit_array_pattern(&mut self, _bit_array: Self::BitArrayPattern) { self.close_currently_open_item(); }