1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use verilization_compiler::*;

use std::env;
use std::ffi::OsString;
use lang::{Language, LanguageRegistry, LanguageHandler};


fn command_version() -> Result<i32, VError> {
	let version = env!("CARGO_PKG_VERSION");
	println!("verilization compiler version {} (native)", version);
	Ok(0)
}

fn command_help() -> Result<i32, VError> {
	let help_message = include_str!("help.txt");
	println!("{}", help_message);
	Ok(0)
}

fn command_generate<Lang: Language>(input_files: Vec<OsString>, options: Lang::Options) -> Result<i32, VError> {
	let model = load_files(input_files)?;

	Lang::generate(&model, options, &mut FileOutputHandler {})?;
	Ok(0)
}

struct ParseGenerateCommand<Args: Iterator<Item = OsString>> {
	args: Args,
}

impl <Args: Iterator<Item = OsString>> LanguageHandler for ParseGenerateCommand<Args> {
	type Result = Result<i32, VError>;

	fn run<Lang: Language>(&mut self) -> Self::Result {
		let mut input_files = Vec::new();
		let mut lang_options = Lang::empty_options();
	
	
		while let Some(arg) = self.args.next() {
			match arg.to_str().unwrap() {
				"-i" => {
					if let Some(filename) = self.args.next() {
						input_files.push(filename)
					}
					else {
						println!("Missing value for input file");
						return Ok(1);
					}
				},
	
				arg => {
					if let Some(option) = arg.strip_prefix("-o:") {
						if let Some(value) = self.args.next() {
							Lang::add_option(&mut lang_options, option, value)?;
						}
						else {
							println!("Missing value for option {}", option);
							return Ok(1);
						}
					}
					else {
						println!("Unknown argument: {}", arg);
						return Ok(1);
					}
				}
			}
		}
	
		let lang_options = Lang::finalize_options(lang_options)?;
	
		command_generate::<Lang>(input_files, lang_options)
	}
}

fn parse_args<Args, Registry: LanguageRegistry>(mut args: Args, registry: &Registry) -> Result<i32, VError> where Args : Iterator<Item = OsString> {
	while let Some(arg) = args.next() {
		match arg.to_str().unwrap() {
			"version" | "--version" | "-v" => return command_version(),
			"help" | "--help" | "-h" => return command_help(),
			"generate" => {
				let lang = match args.next() {
					Some(lang) => lang,
					None => {
						println!("Language not specified");
						return Ok(1);
					},
				};

				let lang = lang.to_str().unwrap();

				match registry.handle_language(lang, &mut ParseGenerateCommand { args }) {
					Some(result) => return result,
					None => {
						println!("Unknown language: {}", lang);
						return Ok(1);
					}
				}
			},
				
			arg => {
				println!("Unexpected argument: {}", arg);
				return Ok(1);
			},
		}
	}

	println!("No command specified");
	Ok(1)
}


pub fn main_impl<Registry: LanguageRegistry>(registry: &Registry) {
	let mut args = env::args_os();
	args.next();

	match parse_args(args, registry) {
		Ok(exit_code) => std::process::exit(exit_code),
		Err(err) => {
			println!("{:?}", err);
			std::process::exit(1)
		},
	}
}