Skip to content

Commit 820b068

Browse files
authored
KCL: Fewer allocations when recasting array expressions (#7854)
Using a `.flat_map` required me to allocate a vector inside the closure. Turning that whole part into a `for` loop that pushed to a vec was faster.
1 parent cef8f9f commit 820b068

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

rust/kcl-lib/src/parsing/ast/types/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,10 @@ impl CallExpressionKw {
19441944
.chain(self.arguments.iter().map(|arg| (arg.label.as_ref(), &arg.arg)))
19451945
}
19461946

1947+
pub fn num_arguments(&self) -> usize {
1948+
self.arguments.len() + if self.unlabeled.is_some() { 1 } else { 0 }
1949+
}
1950+
19471951
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
19481952
if let Some(unlabeled) = &mut self.unlabeled {
19491953
unlabeled.replace_value(source_range, new_value.clone());

rust/kcl-lib/src/unparser.rs

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -527,32 +527,31 @@ impl ArrayExpression {
527527
let num_items = self.elements.len() + self.non_code_meta.non_code_nodes_len();
528528
let mut elems = self.elements.iter();
529529
let mut found_line_comment = false;
530-
let mut format_items: Vec<_> = (0..num_items)
531-
.flat_map(|i| {
532-
if let Some(noncode) = self.non_code_meta.non_code_nodes.get(&i) {
533-
noncode
534-
.iter()
535-
.map(|nc| {
536-
found_line_comment |= nc.value.should_cause_array_newline();
537-
nc.recast(options, 0)
538-
})
539-
.collect::<Vec<_>>()
540-
} else {
541-
let el = elems.next().unwrap();
542-
let s = format!("{}, ", el.recast(options, 0, ExprContext::Other));
543-
vec![s]
544-
}
545-
})
546-
.collect();
530+
let mut format_items: Vec<_> = Vec::with_capacity(num_items);
531+
for i in 0..num_items {
532+
if let Some(noncode) = self.non_code_meta.non_code_nodes.get(&i) {
533+
format_items.extend(noncode.iter().map(|nc| {
534+
found_line_comment |= nc.value.should_cause_array_newline();
535+
nc.recast(options, 0)
536+
}));
537+
} else {
538+
let el = elems.next().unwrap();
539+
let s = format!("{}, ", el.recast(options, 0, ExprContext::Other));
540+
format_items.push(s);
541+
}
542+
}
547543

548544
// Format these items into a one-line array.
549545
if let Some(item) = format_items.last_mut() {
550546
if let Some(norm) = item.strip_suffix(", ") {
551547
*item = norm.to_owned();
552548
}
553549
}
554-
let format_items = format_items; // Remove mutability
555-
let flat_recast = format!("[{}]", format_items.join(""));
550+
let mut flat_recast = "[".to_owned();
551+
for fi in &format_items {
552+
flat_recast.push_str(fi)
553+
}
554+
flat_recast.push(']');
556555

557556
// We might keep the one-line representation, if it's short enough.
558557
let max_array_length = 40;
@@ -562,29 +561,31 @@ impl ArrayExpression {
562561
}
563562

564563
// Otherwise, we format a multi-line representation.
564+
let mut output = "[\n".to_owned();
565565
let inner_indentation = if ctxt == ExprContext::Pipe {
566566
options.get_indentation_offset_pipe(indentation_level + 1)
567567
} else {
568568
options.get_indentation(indentation_level + 1)
569569
};
570-
let formatted_array_lines = format_items
571-
.iter()
572-
.map(|s| {
573-
format!(
574-
"{inner_indentation}{}{}",
575-
if let Some(x) = s.strip_suffix(" ") { x } else { s },
576-
if s.ends_with('\n') { "" } else { "\n" }
577-
)
578-
})
579-
.collect::<Vec<String>>()
580-
.join("")
581-
.to_owned();
570+
for format_item in format_items {
571+
output.push_str(&inner_indentation);
572+
output.push_str(if let Some(x) = format_item.strip_suffix(" ") {
573+
x
574+
} else {
575+
&format_item
576+
});
577+
if !format_item.ends_with('\n') {
578+
output.push('\n')
579+
}
580+
}
582581
let end_indent = if ctxt == ExprContext::Pipe {
583582
options.get_indentation_offset_pipe(indentation_level)
584583
} else {
585584
options.get_indentation(indentation_level)
586585
};
587-
format!("[\n{formatted_array_lines}{end_indent}]")
586+
output.push_str(&end_indent);
587+
output.push(']');
588+
output
588589
}
589590
}
590591

0 commit comments

Comments
 (0)