1
use std::cell::RefCell;
2
use std::error::Error;
3
use std::fs::File;
4
use std::fs::{self};
5
use std::io::Write;
6
use std::process::ExitCode;
7
use std::rc::Rc;
8

            
9
use clap::Parser;
10

            
11
use log::info;
12
use log::warn;
13
use mcrl2::aterm::TermPool;
14
use mcrl2::data::DataSpecification;
15
use mcrl2rewrite::rewrite_data_spec;
16
use mcrl2rewrite::rewrite_rec;
17
use mcrl2rewrite::Rewriter;
18
use sabre::RewriteSpecification;
19

            
20
use crate::trs_format::TrsFormatter;
21

            
22
mod trs_format;
23

            
24
#[cfg(feature = "measure-allocs")]
25
#[global_allocator]
26
static MEASURE_ALLOC: unsafety::AllocCounter = unsafety::AllocCounter;
27

            
28
#[cfg(not(target_env = "msvc"))]
29
#[cfg(not(feature = "measure-allocs"))]
30
#[global_allocator]
31
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
32

            
33
#[derive(clap::Parser, Debug)]
34
#[command(name = "Maurice Laveaux", about = "A command line rewriting tool")]
35
pub(crate) enum Cli {
36
    Rewrite(RewriteArgs),
37
    Convert(ConvertArgs),
38
}
39

            
40
#[derive(clap::Args, Debug)]
41
#[command(about = "Rewrite mCRL2 data specifications and REC files")]
42
struct RewriteArgs {
43
    rewriter: Rewriter,
44

            
45
    #[arg(value_name = "SPEC")]
46
    specification: String,
47

            
48
    #[arg(help = "File containing the terms to be rewritten.")]
49
    terms: Option<String>,
50

            
51
    #[arg(long = "output", default_value_t = false, help = "Print the rewritten term(s)")]
52
    output: bool,
53
}
54

            
55
#[derive(clap::Args, Debug)]
56
#[command(about = "Convert input rewrite system to the TRS format")]
57
struct ConvertArgs {
58
    #[arg(value_name = "SPEC")]
59
    specification: String,
60

            
61
    output: String,
62
}
63

            
64
fn main() -> Result<ExitCode, Box<dyn Error>> {
65
    env_logger::init();
66

            
67
    let cli = Cli::parse();
68
    let tp = Rc::new(RefCell::new(TermPool::new()));
69

            
70
    match cli {
71
        Cli::Rewrite(args) => {
72
            if args.specification.ends_with(".rec") {
73
                assert!(args.terms.is_none());
74
                rewrite_rec(args.rewriter, &args.specification, args.output)?;
75
            } else {
76
                match &args.terms {
77
                    Some(terms) => {
78
                        rewrite_data_spec(tp.clone(), args.rewriter, &args.specification, terms, args.output)?;
79
                    }
80
                    None => {
81
                        warn!("No expressions given to rewrite!");
82
                    }
83
                }
84
            }
85
        }
86
        Cli::Convert(args) => {
87
            // Read the data specification
88
            let data_spec_text = fs::read_to_string(args.specification)?;
89
            let data_spec = DataSpecification::new(&data_spec_text)?;
90

            
91
            let spec: RewriteSpecification = data_spec.into();
92

            
93
            // Check if the lhs only contain constructor sorts.
94
            for rule in &spec.rewrite_rules {
95
                for _t in rule.lhs.iter() {
96
                    //let cons = data_spec.constructors(DataExpressionRef::from(t).sort());
97
                }
98
            }
99

            
100
            let mut output = File::create(args.output)?;
101
            write!(output, "{}", TrsFormatter::new(&spec))?;
102
        }
103
    }
104

            
105
    info!("ATerm pool: {}", tp.borrow());
106

            
107
    #[cfg(feature = "measure-allocs")]
108
    info!("Allocations: {}", MEASURE_ALLOC.number_of_allocations());
109

            
110
    Ok(ExitCode::SUCCESS)
111
}