#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
mod ast;
mod automatize;
mod dot_fmt;
mod linear_passes;
mod linearize;
mod parser;
mod traversals;
mod verify;
pub use self::{
ast::*, automatize::*, linear_passes::*, linearize::*, parser::*, traversals::*, verify::*,
};
use peepmatic_runtime::PeepholeOptimizations;
use peepmatic_traits::TypingRules;
use std::convert::TryFrom;
use std::fmt::Debug;
use std::fs;
use std::hash::Hash;
use std::num::NonZeroU32;
use std::path::Path;
pub fn compile_file<TOperator>(filename: &Path) -> anyhow::Result<PeepholeOptimizations<TOperator>>
where
TOperator: Copy
+ Debug
+ Eq
+ Hash
+ for<'a> wast::parser::Parse<'a>
+ TypingRules
+ Into<NonZeroU32>
+ TryFrom<NonZeroU32>,
{
let source = fs::read_to_string(filename)?;
compile_str::<TOperator>(&source, filename)
}
pub fn compile_str<TOperator>(
source: &str,
filename: &Path,
) -> anyhow::Result<PeepholeOptimizations<TOperator>>
where
TOperator: Copy
+ Debug
+ Eq
+ Hash
+ for<'a> wast::parser::Parse<'a>
+ TypingRules
+ Into<NonZeroU32>
+ TryFrom<NonZeroU32>,
{
let buf = wast::parser::ParseBuffer::new(source).map_err(|mut e| {
e.set_path(filename);
e.set_text(source);
e
})?;
let opts = wast::parser::parse::<Optimizations<'_, TOperator>>(&buf).map_err(|mut e| {
e.set_path(filename);
e.set_text(source);
e
})?;
verify(&opts).map_err(|mut e| {
e.set_path(filename);
e.set_text(source);
e
})?;
let mut opts = crate::linearize(&opts);
sort_least_to_most_general(&mut opts);
remove_unnecessary_nops(&mut opts);
match_in_same_order(&mut opts);
sort_lexicographically(&mut opts);
let automata = automatize(&opts);
let integers = opts.integers;
if let Ok(path) = std::env::var("PEEPMATIC_DOT") {
let f = dot_fmt::PeepholeDotFmt(&integers);
if let Err(e) = automata.write_dot_file(&f, &path) {
panic!(
"failed to write GraphViz Dot file to PEEPMATIC_DOT={}; error: {}",
path, e
);
}
}
Ok(PeepholeOptimizations { integers, automata })
}
#[cfg(test)]
mod tests {
use super::*;
use peepmatic_test_operator::TestOperator;
fn assert_compiles(path: &str) {
match compile_file::<TestOperator>(Path::new(path)) {
Ok(_) => return,
Err(e) => {
eprintln!("error: {}", e);
panic!("error: {}", e);
}
}
}
#[test]
fn compile_redundant_bor() {
assert_compiles("examples/redundant-bor.peepmatic");
}
#[test]
fn mul_by_pow2() {
assert_compiles("examples/mul-by-pow2.peepmatic");
}
#[test]
fn compile_preopt() {
assert_compiles("../codegen/src/preopt.peepmatic");
}
}