diff --git a/src/compare/mod.rs b/src/compare/mod.rs index 65a8f576..b8eeab17 100644 --- a/src/compare/mod.rs +++ b/src/compare/mod.rs @@ -12,5 +12,7 @@ pub use compare::run_compare_on_file; pub use compare::run_compare_on_file_with_settings; pub use compare::silent_anonymous_compare; pub use compare::silent_compare_on_file; +pub(crate) use compare_field::EmacsField; +pub(crate) use elisp_fact::ElispFact; pub use sexp::sexp; pub use sexp::Token; diff --git a/src/wasm/document.rs b/src/wasm/document.rs index 0dfe086b..0232bb63 100644 --- a/src/wasm/document.rs +++ b/src/wasm/document.rs @@ -6,6 +6,7 @@ use super::ast_node::WasmAstNode; use super::macros::to_wasm; use super::standard_properties::WasmStandardProperties; use super::to_wasm::ToWasm; +use crate::compare::ElispFact; use crate::types::Document; use crate::wasm::to_wasm::ToWasmStandardProperties; @@ -70,3 +71,9 @@ impl<'s, 'p> Into> for WasmDocument<'s, 'p> { WasmAstNode::Document(self) } } + +impl<'s, 'p> ElispFact<'s> for WasmDocument<'s, 'p> { + fn get_elisp_name<'b>(&'b self) -> std::borrow::Cow<'s, str> { + "org-data".into() + } +} diff --git a/src/wasm_test/compare.rs b/src/wasm_test/compare.rs index 1e639f13..5b66e4d0 100644 --- a/src/wasm_test/compare.rs +++ b/src/wasm_test/compare.rs @@ -1,9 +1,12 @@ use std::borrow::Cow; use super::elisp_compare::WasmElispCompare; +use crate::compare::ElispFact; +use crate::compare::EmacsField; use crate::compare::Token; use crate::wasm::WasmAstNode; use crate::wasm::WasmDocument; +use crate::wasm_test::macros::wasm_compare; pub fn wasm_compare_document<'b, 's, 'p>( source: &'s str, @@ -54,6 +57,7 @@ impl<'s> WasmDiffResult<'s> { pub fn print(&self, original_document: &str) -> Result<(), Box> { // self.print_indented(0, original_document) + println!("{:#?}", self); todo!() } } @@ -165,7 +169,66 @@ impl<'s, 'p> WasmElispCompare<'s, 'p> for WasmAstNode<'s, 'p> { source: &'s str, emacs: &'b Token<'s>, ) -> Result, Box> { - todo!() + match self { + WasmAstNode::Document(inner) => inner.compare_ast_node(source, emacs), + WasmAstNode::Headline(_) => todo!(), + WasmAstNode::Section(_) => todo!(), + WasmAstNode::Paragraph(_) => todo!(), + WasmAstNode::PlainList(_) => todo!(), + WasmAstNode::PlainListItem(_) => todo!(), + WasmAstNode::CenterBlock(_) => todo!(), + WasmAstNode::QuoteBlock(_) => todo!(), + WasmAstNode::SpecialBlock(_) => todo!(), + WasmAstNode::DynamicBlock(_) => todo!(), + WasmAstNode::FootnoteDefinition(_) => todo!(), + WasmAstNode::Comment(_) => todo!(), + WasmAstNode::Drawer(_) => todo!(), + WasmAstNode::PropertyDrawer(_) => todo!(), + WasmAstNode::NodeProperty(_) => todo!(), + WasmAstNode::Table(_) => todo!(), + WasmAstNode::TableRow(_) => todo!(), + WasmAstNode::VerseBlock(_) => todo!(), + WasmAstNode::CommentBlock(_) => todo!(), + WasmAstNode::ExampleBlock(_) => todo!(), + WasmAstNode::ExportBlock(_) => todo!(), + WasmAstNode::SrcBlock(_) => todo!(), + WasmAstNode::Clock(_) => todo!(), + WasmAstNode::DiarySexp(_) => todo!(), + WasmAstNode::Planning(_) => todo!(), + WasmAstNode::FixedWidthArea(_) => todo!(), + WasmAstNode::HorizontalRule(_) => todo!(), + WasmAstNode::Keyword(_) => todo!(), + WasmAstNode::BabelCall(_) => todo!(), + WasmAstNode::LatexEnvironment(_) => todo!(), + WasmAstNode::Bold(_) => todo!(), + WasmAstNode::Italic(_) => todo!(), + WasmAstNode::Underline(_) => todo!(), + WasmAstNode::StrikeThrough(_) => todo!(), + WasmAstNode::Code(_) => todo!(), + WasmAstNode::Verbatim(_) => todo!(), + WasmAstNode::PlainText(_) => todo!(), + WasmAstNode::RegularLink(_) => todo!(), + WasmAstNode::RadioLink(_) => todo!(), + WasmAstNode::RadioTarget(_) => todo!(), + WasmAstNode::PlainLink(_) => todo!(), + WasmAstNode::AngleLink(_) => todo!(), + WasmAstNode::OrgMacro(_) => todo!(), + WasmAstNode::Entity(_) => todo!(), + WasmAstNode::LatexFragment(_) => todo!(), + WasmAstNode::ExportSnippet(_) => todo!(), + WasmAstNode::FootnoteReference(_) => todo!(), + WasmAstNode::Citation(_) => todo!(), + WasmAstNode::CitationReference(_) => todo!(), + WasmAstNode::InlineBabelCall(_) => todo!(), + WasmAstNode::InlineSourceBlock(_) => todo!(), + WasmAstNode::LineBreak(_) => todo!(), + WasmAstNode::Target(_) => todo!(), + WasmAstNode::StatisticsCookie(_) => todo!(), + WasmAstNode::Subscript(_) => todo!(), + WasmAstNode::Superscript(_) => todo!(), + WasmAstNode::TableCell(_) => todo!(), + WasmAstNode::Timestamp(_) => todo!(), + } } } @@ -175,10 +238,17 @@ impl<'s, 'p> WasmElispCompare<'s, 'p> for WasmDocument<'s, 'p> { source: &'s str, emacs: &'b Token<'s>, ) -> Result, Box> { - let mut result = WasmDiffResult::default(); - let emacs_children = emacs.as_list()?.iter().skip(2); - let wasm_children = self.children.iter(); - result.extend(wasm_compare_list(source, emacs_children, wasm_children)?)?; - todo!() + let result = wasm_compare!( + source, + emacs, + self, + ( + EmacsField::Required(":path"), + |w| w.path.as_ref().and_then(|p| p.to_str()), + || true + ) + ); + // todo: compare the rest + Ok(result) } } diff --git a/src/wasm_test/macros.rs b/src/wasm_test/macros.rs new file mode 100644 index 00000000..db834c5e --- /dev/null +++ b/src/wasm_test/macros.rs @@ -0,0 +1,69 @@ +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> = + emacs_attributes_map.keys().map(|s| *s).collect(); + + { + // Compare name + 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 + result.extend(wasm_compare_list( + $source, + emacs_list_iter, + $wasm.children.iter(), + )?)?; + } + + { + // Compare fields + $( + 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) => {} + } + )* + } + + result + }}; +} +pub(crate) use wasm_compare; diff --git a/src/wasm_test/mod.rs b/src/wasm_test/mod.rs index 0d264593..3a5b67da 100644 --- a/src/wasm_test/mod.rs +++ b/src/wasm_test/mod.rs @@ -1,5 +1,6 @@ mod compare; mod elisp_compare; +mod macros; mod runner; pub use runner::wasm_run_anonymous_compare;