Files
organic/src/wasm_test/macros.rs

110 lines
3.6 KiB
Rust
Raw Normal View History

2023-12-27 15:14:42 -05:00
macro_rules! wasm_compare {
($source:expr, $emacs:expr, $wasm:expr, $(($emacs_field:expr, $wasm_value_getter:expr, $compare_fn: expr)),*) => {{
let mut result = WasmDiffResult::default();
let emacs_list = $emacs.as_list()?;
let mut emacs_list_iter = emacs_list.iter();
let emacs_name = emacs_list_iter
.next()
.ok_or("Should have an attributes child.")?
.as_atom()?;
let emacs_attributes_map = emacs_list_iter
.next()
.ok_or("Should have an attributes child.")?
.as_map()?;
let mut emacs_keys: std::collections::BTreeSet<&str> =
2023-12-27 16:40:55 -05:00
emacs_attributes_map.keys().map(|s| *s).collect();
// Mark :standard-properties as seen because it will be handled separately.
if emacs_keys.contains(":standard-properties") {
emacs_keys.remove(":standard-properties");
} else {
result.status.push(WasmDiffStatus::Bad(
"Emacs node lacked :standard-properties field.".into(),
));
}
2023-12-27 15:14:42 -05:00
{
// Compare name.
2023-12-27 15:14:42 -05:00
let wasm_name = $wasm.get_elisp_name();
if emacs_name != wasm_name {
result.status.push(WasmDiffStatus::Bad(
format!(
"AST node name mismatch. Emacs=({emacs}) Wasm=({wasm}).",
emacs = emacs_name,
wasm = wasm_name,
)
.into(),
));
}
}
{
// Compare children.
2023-12-27 16:47:02 -05:00
result.extend(wasm_compare_list(
$source,
emacs_list_iter,
$wasm.children.iter(),
)?)?;
2023-12-27 15:14:42 -05:00
}
{
// Check for properties that are missing from the elisp node.
2023-12-27 15:14:42 -05:00
$(
match $emacs_field {
EmacsField::Required(name) if emacs_keys.contains(name) => {
emacs_keys.remove(name);
}
EmacsField::Optional(name) if emacs_keys.contains(name) => {
emacs_keys.remove(name);
}
EmacsField::Required(name) => {
result.status.push(WasmDiffStatus::Bad(
format!(
"Emacs node lacked required field ({name}).",
name = name,
)
.into(),
));
}
EmacsField::Optional(_name) => {}
}
)*
}
{
// Check for elisp properties that were not compared.
if !emacs_keys.is_empty() {
let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect();
let unexpected_keys = unexpected_keys.join(", ");
result.status.push(WasmDiffStatus::Bad(
format!(
"Emacs node had extra field(s): ({field_names}).",
field_names = unexpected_keys,
)
.into(),
));
}
}
{
// Compare properties.
$(
let emacs_name = match $emacs_field {
EmacsField::Required(name) => {
name
},
EmacsField::Optional(name) => {
name
},
};
2023-12-27 16:40:55 -05:00
result.extend($compare_fn($source, $emacs, $wasm, emacs_name, $wasm_value_getter)?)?;
)*
}
2023-12-27 15:14:42 -05:00
result
}};
}
pub(crate) use wasm_compare;