use super::super::super::HighLevelEmitter;
pub(super) fn resolve_condition_expression(
statements: &[String],
header_index: usize,
condition: &str,
) -> Option<String> {
if condition.contains("==") {
return Some(condition.trim().to_string());
}
let condition = condition.trim();
let condition = condition
.strip_prefix('!')
.map(str::trim)
.unwrap_or(condition);
let prev = HighLevelEmitter::previous_code_line(statements, header_index)?;
let assign = HighLevelEmitter::parse_assignment(statements[prev].as_str())?;
(assign.lhs == condition).then_some(assign.rhs)
}
pub(super) fn parse_case_sides(condition: &str) -> Option<(String, &str)> {
let (left, right) = split_equals(condition)?;
let left = left.trim();
let right = right.trim();
if is_literal(left) && !is_literal(right) {
return Some((right.to_string(), left));
}
if !is_literal(left) && is_literal(right) {
return Some((left.to_string(), right));
}
if is_temp(left) && !is_temp(right) {
return Some((right.to_string(), left));
}
if is_temp(right) && !is_temp(left) {
return Some((left.to_string(), right));
}
None
}
pub(super) fn resolve_case_value(
statements: &[String],
header_index: usize,
token: &str,
) -> Option<String> {
if is_literal(token) {
return Some(token.trim().to_string());
}
if !is_temp(token) {
return None;
}
let mut cursor = header_index;
while let Some(prev) = HighLevelEmitter::previous_code_line(statements, cursor) {
cursor = prev;
let Some(assign) = HighLevelEmitter::parse_assignment(statements[prev].as_str()) else {
continue;
};
if assign.lhs != token {
continue;
}
let rhs = assign.rhs.trim().to_string();
return is_literal(rhs.as_str()).then_some(rhs);
}
None
}
pub(super) fn is_literal(value: &str) -> bool {
let value = value.trim();
if value.is_empty() {
return false;
}
if value.starts_with('"') && value.ends_with('"') && value.len() >= 2 {
return true;
}
if value.starts_with('\'') && value.ends_with('\'') && value.len() >= 3 {
return true;
}
if matches!(value, "true" | "false" | "null") {
return true;
}
if value.starts_with("0x") && value.len() > 2 {
return value[2..].chars().all(|ch| ch.is_ascii_hexdigit());
}
value.parse::<i64>().is_ok()
}
pub(super) fn is_temp(value: &str) -> bool {
let value = value.trim();
value.len() > 1 && value.starts_with('t') && value[1..].bytes().all(|b| b.is_ascii_digit())
}
pub(super) fn parse_inline_if_goto(line: &str) -> Option<(String, String)> {
let line = line.trim();
let rest = line.strip_prefix("if ")?;
let (condition, suffix) = rest.split_once(" { goto ")?;
let label = suffix.strip_suffix("; }")?.trim();
if label.is_empty() {
return None;
}
Some((condition.trim().to_string(), label.to_string()))
}
pub(super) fn parse_plain_goto_label(line: &str) -> Option<String> {
let line = line.trim();
let label = line.strip_prefix("goto ")?.strip_suffix(';')?.trim();
if label.is_empty() {
return None;
}
Some(label.to_string())
}
pub(super) fn parse_label_line(line: &str) -> Option<String> {
let line = line.trim();
let label = line.strip_suffix(':')?.trim();
if !label.starts_with("label_") {
return None;
}
Some(label.to_string())
}
fn split_equals(condition: &str) -> Option<(&str, &str)> {
let pos = condition.find("==")?;
let (left, rest) = condition.split_at(pos);
let right = rest.strip_prefix("==")?;
Some((left, right))
}