use super::super::HighLevelEmitter;
mod basic;
mod indexed;
mod reorder;
mod reverse;
fn forget_stack_value(emitter: &mut HighLevelEmitter, value: &str) {
emitter.literal_values.remove(value);
emitter.packed_values_by_name.remove(value);
}
fn replace_dynamic_stack_survivors(emitter: &mut HighLevelEmitter, helper: &str, argument: &str) {
let old_values = emitter.stack.clone();
for value in old_values {
forget_stack_value(emitter, &value);
}
let len = emitter.stack.len();
for (index, value) in emitter.stack.iter_mut().enumerate() {
let depth_from_top = len - 1 - index;
let base = format!("{helper}({argument})");
*value = if depth_from_top == 0 {
base
} else {
format!("{base}[{depth_from_top}]")
};
}
}
pub(super) fn is_simple_literal_or_identifier(value: &str) -> bool {
let trimmed = value.trim();
if trimmed.is_empty() {
return false;
}
let no_sign = trimmed.strip_prefix('-').unwrap_or(trimmed);
if !no_sign.is_empty() && no_sign.chars().all(|c| c.is_ascii_digit()) {
return true;
}
if let Some(hex) = trimmed
.strip_prefix("0x")
.or_else(|| trimmed.strip_prefix("0X"))
{
if !hex.is_empty() && hex.chars().all(|c| c.is_ascii_hexdigit()) {
return true;
}
}
if matches!(trimmed, "true" | "false" | "null") {
return true;
}
if trimmed.len() >= 2 && trimmed.starts_with('"') && trimmed.ends_with('"') {
let inner = &trimmed[1..trimmed.len() - 1];
if !inner.contains('"') || string_has_only_escaped_quotes(inner) {
return true;
}
}
let mut chars = trimmed.chars();
if let Some(first) = chars.next() {
if (first.is_ascii_alphabetic() || first == '_')
&& chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
{
return true;
}
}
false
}
fn string_has_only_escaped_quotes(inner: &str) -> bool {
let bytes = inner.as_bytes();
let mut i = 0;
while i < bytes.len() {
if bytes[i] == b'"' {
let mut backslashes = 0;
let mut j = i;
while j > 0 && bytes[j - 1] == b'\\' {
backslashes += 1;
j -= 1;
}
if backslashes % 2 == 0 {
return false;
}
}
i += 1;
}
true
}