1
use std::fmt::Debug;
2
use std::time::Instant;
3

            
4
use clap::ValueEnum;
5

            
6
use merc_data::to_untyped_data_expression;
7
use merc_rec_tests::load_rec_from_file;
8
use merc_sabre::InnermostRewriter;
9
use merc_sabre::NaiveRewriter;
10
use merc_sabre::RewriteEngine;
11
use merc_sabre::SabreRewriter;
12
use merc_utilities::MercError;
13

            
14
/// Selects the rewriter to use.
15
#[derive(ValueEnum, Debug, Clone)]
16
pub enum Rewriter {
17
    Naive,
18
    Innermost,
19
    Sabre,
20
}
21

            
22
/// Rewrites the given REC specification.
23
pub fn rewrite_rec(rewriter: Rewriter, filename_specification: &str, output: bool) -> Result<(), MercError> {
24
    let (syntax_spec, syntax_terms) = load_rec_from_file(filename_specification.into())?;
25

            
26
    let spec = syntax_spec.to_rewrite_spec();
27

            
28
    match rewriter {
29
        Rewriter::Naive => {
30
            let mut inner = NaiveRewriter::new(&spec);
31

            
32
            let now = Instant::now();
33
            for term in &syntax_terms {
34
                let term = to_untyped_data_expression(term.clone(), None);
35
                let result = inner.rewrite(&term);
36
                if output {
37
                    println!("{}", result)
38
                }
39
            }
40
            println!("Naive rewrite took {} ms", now.elapsed().as_millis());
41
        }
42
        Rewriter::Innermost => {
43
            let mut inner = InnermostRewriter::new(&spec);
44

            
45
            let now = Instant::now();
46
            for term in &syntax_terms {
47
                let term = to_untyped_data_expression(term.clone(), None);
48
                let result = inner.rewrite(&term);
49
                if output {
50
                    println!("{}", result)
51
                }
52
            }
53
            println!("Innermost rewrite took {} ms", now.elapsed().as_millis());
54
        }
55
        Rewriter::Sabre => {
56
            let mut sa = SabreRewriter::new(&spec);
57

            
58
            let now = Instant::now();
59
            for term in &syntax_terms {
60
                let term = to_untyped_data_expression(term.clone(), None);
61
                let result = sa.rewrite(&term);
62
                if output {
63
                    println!("{}", result)
64
                }
65
            }
66
            println!("Sabre rewrite took {} ms", now.elapsed().as_millis());
67
        }
68
    }
69

            
70
    Ok(())
71
}