use crate::Emitter;
use crate::names::go_name;
use crate::utils::Staged;
use crate::write_line;
use syntax::ast::Expression;
impl Emitter<'_> {
pub(crate) fn emit_or_capture(
&mut self,
output: &mut String,
expression: &Expression,
prefix: &str,
) -> String {
let emit_directly = matches!(
expression,
Expression::Literal { .. } | Expression::Identifier { .. }
);
if emit_directly {
return self.emit_operand(output, expression);
}
let temp_var = self.fresh_var(Some(prefix));
self.declare(&temp_var);
let expression_string = self.emit_operand(output, expression);
write_line!(output, "{} := {}", temp_var, expression_string);
temp_var
}
pub(crate) fn emit_force_capture(
&mut self,
output: &mut String,
expression: &Expression,
prefix: &str,
) -> String {
if matches!(expression.unwrap_parens(), Expression::Literal { .. }) {
return self.emit_operand(output, expression);
}
let temp_var = self.fresh_var(Some(prefix));
self.declare(&temp_var);
let expression_string = self.emit_composite_value(output, expression);
write_line!(output, "{} := {}", temp_var, expression_string);
temp_var
}
pub(crate) fn stage_operand(&mut self, expression: &Expression) -> Staged {
let mut setup = String::new();
let value = self.emit_operand(&mut setup, expression);
Staged::new(setup, value)
}
pub(crate) fn stage_composite(&mut self, expression: &Expression) -> Staged {
let mut setup = String::new();
let value = self.emit_composite_value(&mut setup, expression);
Staged::new(setup, value)
}
pub(crate) fn sequence_with_spread(
&mut self,
output: &mut String,
mut stages: Vec<Staged>,
spread: Option<&Expression>,
wrap_to_any: bool,
prefix: &str,
) -> Vec<String> {
let spread_idx = spread.map(|s| {
stages.push(self.stage_operand(s));
stages.len() - 1
});
let mut values = self.sequence(output, stages, prefix);
if let Some(i) = spread_idx {
if wrap_to_any {
self.flags.needs_stdlib = true;
values[i] = format!("{}.SliceToAny({})", go_name::GO_STDLIB_PKG, values[i]);
}
values[i].push_str("...");
}
values
}
pub(crate) fn sequence(
&mut self,
output: &mut String,
stages: Vec<Staged>,
prefix: &str,
) -> Vec<String> {
if stages.iter().all(|s| s.setup.is_empty()) {
return stages.into_iter().map(|s| s.value).collect();
}
let mut results = Vec::with_capacity(stages.len());
for (i, s) in stages.iter().enumerate() {
let later_has_setup = stages[i + 1..].iter().any(|s| !s.setup.is_empty());
output.push_str(&s.setup);
if later_has_setup && s.has_side_effects {
let tmp = self.fresh_var(Some(prefix));
self.declare(&tmp);
write_line!(output, "{} := {}", tmp, s.value);
results.push(tmp);
} else {
results.push(s.value.clone());
}
}
results
}
}