moleculec_go/
lib.rs

1use std::{
2    io::{self, Read, Write},
3    process,
4};
5
6use molecule_codegen::IntermediateFormat;
7
8mod codegen;
9
10use codegen::Generator;
11
12pub(crate) enum AppAction {
13    DisplayFormat,
14    ProcessIntermediate(Vec<u8>),
15}
16
17pub struct AppConfig {
18    action: AppAction,
19    format: IntermediateFormat,
20}
21
22type RawAppConfig = (IntermediateFormat, clap::ArgMatches);
23
24pub fn build_commandline(format: IntermediateFormat) -> AppConfig {
25    let matches = clap::Command::new("moleculec-go")
26        .name("Moleculec Plugin")
27        .about("Compiler plugin for molecule to generate code.")
28        .version(clap::crate_version!())
29        .arg(
30            clap::Arg::new("format")
31                .long("format")
32                .help("Output the supported format for the intermediate data.")
33                .action(clap::ArgAction::SetTrue),
34        )
35        .get_matches();
36    AppConfig::from((format, matches))
37}
38
39impl From<RawAppConfig> for AppConfig {
40    fn from(input: RawAppConfig) -> Self {
41        let (format, matches) = input;
42        let action = if matches.get_flag("format") {
43            AppAction::DisplayFormat
44        } else {
45            let mut input = Vec::new();
46            if io::stdin().read_to_end(&mut input).is_err() {
47                eprintln!("Error: failed to read data from stdin)");
48                process::exit(1);
49            };
50            AppAction::ProcessIntermediate(input)
51        };
52        Self { action, format }
53    }
54}
55
56impl AppConfig {
57    pub fn execute(self) {
58        match self.action {
59            AppAction::DisplayFormat => {
60                println!("{}", self.format);
61            }
62            AppAction::ProcessIntermediate(input) => {
63                let ast = self.format.recover(&input).unwrap();
64
65                let mut output_data = Vec::<u8>::new();
66
67                if let Err(err) = Generator::generate(&mut output_data, &ast) {
68                    eprintln!("failed to write data by generator: {}", err)
69                }
70
71                let stdout = io::stdout();
72                let mut stdout_handle = stdout.lock();
73                stdout_handle.write_all(&output_data).unwrap();
74                stdout_handle.flush().unwrap();
75            }
76        }
77    }
78}