···3939 let mut variables = Variables::new(expression_generator);
4040 let assignments = variables.assign_case_subjects(compiled_case, subjects)?;
4141 let decision = CasePrinter { clauses, variables }.decision(&compiled_case.tree)?;
4242- Ok(docvec![assignments_to_doc(assignments), decision].force_break())
4242+ Ok(docvec![assignments_to_doc(assignments), decision.into_doc()].force_break())
4343+}
4444+4545+enum CaseBody<'a> {
4646+ If(Document<'a>),
4747+ Statements(Document<'a>),
4848+}
4949+5050+impl<'a> CaseBody<'a> {
5151+ fn into_doc(self) -> Document<'a> {
5252+ match self {
5353+ CaseBody::If(document) | CaseBody::Statements(document) => document,
5454+ }
5555+ }
4356}
44574558struct CasePrinter<'module, 'generator, 'a> {
···101114///
102115/// So, as we're generating code for each check and move further down the decision
103116/// tree, we will have to keep track of all the variables that we've discovered
104104-/// after each successfull check.
117117+/// after each successful check.
105118///
106119/// In order to do that we'll be using a `Variables` data structure to hold all
107120/// this information about the current scope. This also allows us to reuse a lot
···109122/// the decision tree of let expressions!
110123///
111124impl<'a> CasePrinter<'_, '_, 'a> {
112112- fn decision(&mut self, decision: &'a Decision) -> Output<'a> {
125125+ fn decision(&mut self, decision: &'a Decision) -> Result<CaseBody<'a>, Error> {
113126 match decision {
114127 Decision::Fail => unreachable!("Invalid decision tree reached code generation"),
115128 Decision::Run { body } => {
116129 let bindings = self.variables.bindings_doc(&body.bindings);
117130 let body = self.body_expression(body.clause_index)?;
118118- Ok(join_with_line(bindings, body))
131131+ Ok(CaseBody::Statements(join_with_line(bindings, body)))
119132 }
120133 Decision::Switch {
121134 var,
···149162 choices: &'a [(RuntimeCheck, Box<Decision>)],
150163 fallback: &'a Decision,
151164 fallback_check: &'a FallbackCheck,
152152- ) -> Output<'a> {
165165+ ) -> Result<CaseBody<'a>, Error> {
153166 // If there's just a single choice we can just generate the code for
154167 // it: no need to do any checking, we know it must match!
155168 if choices.is_empty() {
···200213 } else {
201214 docvec![" else if (", check_doc, ") "]
202215 };
203203- if_ = if_.append(docvec![branch, break_block(body?)]);
216216+ if_ = if_.append(docvec![branch, break_block(body?.into_doc())]);
204217 }
205218206219 // In case there's some new variables we can extract after the
···212225 }
213226214227 let body = self.inside_new_scope(|this| this.decision(fallback))?;
228228+ let (body, wrap_body_in_block) = match body {
229229+ CaseBody::If(document) => (document, false),
230230+ CaseBody::Statements(document) => (document, true),
231231+ };
232232+233233+ let has_assignments = !assignments.is_empty();
234234+215235 let if_ = join_with_line(join(assignments, line()), if_);
216216- Ok(if body.is_empty() {
236236+ let document = if body.is_empty() {
217237 if_
218218- } else {
238238+ } else if wrap_body_in_block {
219239 docvec![if_, " else ", break_block(body)]
240240+ } else {
241241+ docvec![if_, " else ", body]
242242+ };
243243+244244+ Ok(if has_assignments {
245245+ CaseBody::Statements(document)
246246+ } else {
247247+ CaseBody::If(document)
220248 })
221249 }
222250···245273 guard: usize,
246274 if_true: &'a Body,
247275 if_false: &'a Decision,
248248- ) -> Output<'a> {
276276+ ) -> Result<CaseBody<'a>, Error> {
249277 let guard = self
250278 .clauses
251279 .get(guard)
···272300 let if_true_body = this.body_expression(if_true.clause_index)?;
273301 Ok(join_with_line(if_true_bindings, if_true_body))
274302 })?;
275275- let if_false = self.inside_new_scope(|this| this.decision(if_false))?;
303303+ let if_false = self
304304+ .inside_new_scope(|this| this.decision(if_false))?
305305+ .into_doc();
276306277307 // We can now piece everything together into a single document!
278308 let if_ = docvec!["if (", check, ") ", break_block(if_true)];
309309+ let has_assignments = !check_bindings.is_empty();
310310+279311 let if_ = join_with_line(check_bindings, if_);
280280- if if_false.is_empty() {
281281- Ok(docvec![if_])
312312+ let document = if if_false.is_empty() {
313313+ if_
282314 } else {
283315 let else_ = docvec![" else ", break_block(if_false)];
284284- Ok(docvec![if_, else_])
285285- }
316316+ docvec![if_, else_]
317317+ };
318318+ Ok(if has_assignments {
319319+ CaseBody::Statements(document)
320320+ } else {
321321+ CaseBody::If(document)
322322+ })
286323 }
287324}
288325