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}