1
use std::fmt::Debug;
2

            
3
use clap::ValueEnum;
4

            
5
use merc_aterm::ATerm;
6
use merc_data::to_untyped_data_expression;
7
use merc_sabre::InnermostRewriter;
8
use merc_sabre::NaiveRewriter;
9
use merc_sabre::RewriteEngine;
10
use merc_sabre::RewriteSpecification;
11
use merc_sabre::SabreRewriter;
12
use merc_sabre_compiling::SabreCompilingRewriter;
13
use merc_utilities::MercError;
14
use merc_utilities::Timing;
15

            
16
/// Selects the rewriter to use.
17
#[derive(ValueEnum, Debug, Clone)]
18
pub enum Rewriter {
19
    Naive,
20
    /// An innermost rewriter that uses set automata for efficient matching.
21
    Innermost,
22
    /// A variant of innermost that generates Rust code for the rewrite rules and compiles it to a dynamic library.
23
    InnermostCompiling,
24
    /// A set automaton-based rewriter that applies rules outermost.
25
    Sabre,
26
}
27

            
28
/// Rewrites the given REC specification.
29
pub fn rewrite_rec(
30
    rewriter: Rewriter,
31
    spec: &RewriteSpecification,
32
    syntax_terms: &[ATerm],
33
    output: bool,
34
    timing: &Timing,
35
) -> Result<(), MercError> {
36
    match rewriter {
37
        Rewriter::Naive => {
38
            let mut inner = timing.measure("rewriter_construction", || NaiveRewriter::new(spec));
39

            
40
            timing.measure("rewrite_rec", || {
41
                for term in syntax_terms {
42
                    let term = to_untyped_data_expression(term.clone(), None);
43
                    let result = inner.rewrite(&term);
44
                    if output {
45
                        println!("{}", result)
46
                    }
47
                }
48
            });
49
        }
50
        Rewriter::Innermost => {
51
            let mut inner = timing.measure("rewriter_construction", || InnermostRewriter::new(spec));
52

            
53
            timing.measure("rewrite_rec", || {
54
                for term in syntax_terms {
55
                    let term = to_untyped_data_expression(term.clone(), None);
56
                    let result = inner.rewrite(&term);
57
                    if output {
58
                        println!("{}", result)
59
                    }
60
                }
61
            });
62
        }
63
        Rewriter::InnermostCompiling => {
64
            let mut inner = timing.measure("rewriter_construction", || {
65
                SabreCompilingRewriter::new(spec, true, false)
66
            })?;
67

            
68
            timing.measure("rewrite_rec", || {
69
                for term in syntax_terms {
70
                    let term = to_untyped_data_expression(term.clone(), None);
71
                    let result = inner.rewrite(&term);
72
                    if output {
73
                        println!("{}", result)
74
                    }
75
                }
76
            });
77
        }
78
        Rewriter::Sabre => {
79
            let mut sa = timing.measure("rewriter_construction", || SabreRewriter::new(spec));
80

            
81
            timing.measure("rewrite_rec", || {
82
                for term in syntax_terms {
83
                    let term = to_untyped_data_expression(term.clone(), None);
84
                    let result = sa.rewrite(&term);
85
                    if output {
86
                        println!("{}", result)
87
                    }
88
                }
89
            });
90
        }
91
    }
92

            
93
    Ok(())
94
}