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

Configure Feed

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

avoid allocating vec for pipeline docs

author
Giacomo Cavalieri
committer
Louis Pilfold
date (Jun 15, 2026, 12:37 PM +0100) commit 00116641 parent 85608332 change-id nwmyyxut
+58 -47
+58 -32
compiler-core/src/format.rs
··· 1434 1434 ) -> Document<'a, 'doc> { 1435 1435 let mut previous_position = 0; 1436 1436 let count = statements.len(); 1437 + 1437 1438 let mut documents = Vec::with_capacity(count * 2); 1438 1439 for (i, statement) in statements.iter().enumerate() { 1439 1440 let preceding_newline = self.pop_empty_lines(previous_position + 1); ··· 1458 1459 .first() 1459 1460 .is_some_and(|statement| statement.is_expression()) 1460 1461 { 1461 - documents.to_doc(arena) 1462 + arena.concat(documents) 1462 1463 } else { 1463 - documents.to_doc(arena).force_break(arena) 1464 + arena.concat(documents).force_break(arena) 1464 1465 } 1465 1466 } 1466 1467 ··· 2309 2310 expressions: &'a Vec1<UntypedExpr>, 2310 2311 nest_pipe: bool, 2311 2312 ) -> Document<'a, 'doc> { 2312 - let mut docs = Vec::with_capacity(expressions.len() * 3); 2313 + // We start by producing the document for the first step of the pipeline. 2313 2314 let first = expressions.first(); 2314 2315 let first_precedence = first.bin_op_precedence(); 2315 2316 let first = self.expr(arena, cache, first).group(arena); 2316 - docs.push(self.operator_side(arena, cache, first, 5, first_precedence)); 2317 + let first_step = self.operator_side(arena, cache, first, 5, first_precedence); 2317 2318 2319 + // We then produce a doc for each item in the rest of the pipeline. 2318 2320 let pipeline_start = expressions.first().location().start; 2319 2321 let pipeline_end = expressions.last().location().end; 2320 2322 let try_to_keep_on_one_line = !self.spans_multiple_lines(pipeline_start, pipeline_end); 2323 + let steps_separator = if try_to_keep_on_one_line { 2324 + cache.breakable_space 2325 + } else { 2326 + cache.line 2327 + }; 2321 2328 2322 - for expression in expressions.iter().skip(1) { 2329 + let other_steps = expressions.iter().skip(1).map(|expression| { 2330 + // We start by producing the document for the pipe itself `|>`, 2331 + // we also want to put comments before it! 2323 2332 let comments = self.pop_comments(expression.location().start); 2324 - let doc = if let UntypedExpr::Fn { kind, body, .. } = expression 2325 - && kind.is_capture() 2326 - { 2327 - self.fn_capture(arena, cache, body, FnCapturePosition::RightHandSideOfPipe) 2328 - } else { 2329 - self.expr(arena, cache, expression) 2333 + let commented_pipe = commented(arena, cache, cache.pipe_space, comments); 2334 + let mut pipe = docvec_arena![arena, steps_separator, commented_pipe]; 2335 + if nest_pipe { 2336 + pipe = pipe.nest(arena, INDENT); 2330 2337 }; 2331 - let doc = if nest_pipe { 2332 - doc.nest(arena, INDENT) 2333 - } else { 2334 - doc 2335 - }; 2336 - let space = if try_to_keep_on_one_line { 2337 - cache.breakable_space 2338 - } else { 2339 - cache.line 2340 - }; 2341 - let pipe = space.append(arena, commented(arena, cache, cache.pipe_space, comments)); 2342 - let pipe = if nest_pipe { 2343 - pipe.nest(arena, INDENT) 2344 - } else { 2345 - pipe 2346 - }; 2347 - docs.push(pipe); 2348 - docs.push(self.operator_side(arena, cache, doc, 4, expression.bin_op_precedence())); 2338 + 2339 + // We then produce the document for the expression being piped into. 2340 + let expression_doc = 2341 + self.expression_on_right_hand_side_of_pipe(arena, cache, nest_pipe, expression); 2342 + let expression_doc = self.operator_side( 2343 + arena, 2344 + cache, 2345 + expression_doc, 2346 + 4, 2347 + expression.bin_op_precedence(), 2348 + ); 2349 + 2350 + // And finally piece everything together. 2351 + pipe.append(arena, expression_doc) 2352 + }); 2353 + 2354 + let stops = std::iter::once(first_step).chain(other_steps); 2355 + if try_to_keep_on_one_line { 2356 + arena.concat(stops) 2357 + } else { 2358 + arena.concat(stops).force_break(arena) 2349 2359 } 2360 + } 2350 2361 2351 - if try_to_keep_on_one_line { 2352 - docs.to_doc(arena) 2362 + fn expression_on_right_hand_side_of_pipe( 2363 + &mut self, 2364 + arena: &'doc DocumentArena<'a, 'doc>, 2365 + cache: &'doc FormatterCache<'a, 'doc>, 2366 + nest_pipe: bool, 2367 + expression: &'a UntypedExpr, 2368 + ) -> Document<'a, 'doc> { 2369 + let expression = if let UntypedExpr::Fn { kind, body, .. } = expression 2370 + && kind.is_capture() 2371 + { 2372 + self.fn_capture(arena, cache, body, FnCapturePosition::RightHandSideOfPipe) 2353 2373 } else { 2354 - docs.to_doc(arena).force_break(arena) 2374 + self.expr(arena, cache, expression) 2375 + }; 2376 + 2377 + if nest_pipe { 2378 + expression.nest(arena, INDENT) 2379 + } else { 2380 + expression 2355 2381 } 2356 2382 } 2357 2383
-15
compiler-core/src/pretty_arena.rs
··· 51 51 /// 52 52 #[macro_export] 53 53 macro_rules! docvec_arena { 54 - () => { 55 - Document::Vec(Vec::new()) 56 - }; 57 - 58 54 ($arena:expr, $first:expr, $second:expr, $third:expr) => { 59 55 $arena.join3($first, $second, $third) 60 56 }; ··· 63 59 $arena.join4($first, $second, $third, $fourth) 64 60 }; 65 61 66 - // A docvec![] with multiple elements. 67 62 ($arena:expr, $first:expr, $($rest:expr),+ $(,)?) => { 68 - // A document that looks like this: `Vec[Vec[..rest], ..other_rest]` 69 - // is exactly the same as a flat: `Vec[..rest, ..other_rest]`. 70 - // So in case a `docvec!` starts with a `Vec` we flatten it out to avoid 71 - // having deeply nested documents. 72 63 { 73 64 $first.to_doc(&$arena) 74 65 $(.append(&$arena, $rest))+ ··· 179 170 impl<'string, 'doc> Documentable<'string, 'doc> for Document<'string, 'doc> { 180 171 fn to_doc(self, _arena: &'doc DocumentArena<'string, 'doc>) -> Document<'string, 'doc> { 181 172 self 182 - } 183 - } 184 - 185 - impl<'string, 'doc> Documentable<'string, 'doc> for Vec<Document<'string, 'doc>> { 186 - fn to_doc(self, arena: &'doc DocumentArena<'string, 'doc>) -> Document<'string, 'doc> { 187 - arena.concat(self) 188 173 } 189 174 } 190 175