#[macro_use] extern crate log; use std::collections::HashMap; use std::sync::Arc; use clappconfig::{AppConfig, clap}; use clappconfig::clap::ArgMatches; use serde::{Deserialize, Serialize}; use crsn::asm::data::literal::Addr; use crsn::runtime::run_thread::{RunThread, ThreadToken}; use crsn_arith::ArithOps; use crsn_screen::ScreenOps; use crsn_stacks::StackOps; mod read_file; #[derive(Debug, Clone, Serialize, Deserialize)] struct LogConfig { level: String, modules: HashMap, } #[derive(Debug, Clone, Serialize, Deserialize)] struct Config { log: LogConfig, #[serde(skip)] program_file: String, } impl Default for Config { fn default() -> Self { Self { log: LogConfig { level: "info".to_string(), modules: Default::default(), }, program_file: "".to_string(), } } } impl AppConfig for Config { type Init = Self; fn logging(&self) -> &str { &self.log.level } fn logging_mod_levels(&self) -> Option<&HashMap> { Some(&self.log.modules) } /// Add args to later use in the `configure` method. fn add_args<'a: 'b, 'b>(clap: clap::App<'a, 'b>) -> clap::App<'a, 'b> { // Default impl clap.arg( clap::Arg::with_name("input") .value_name("FILE") .help("Program to run") .required_unless("default-config") .takes_value(true), ) } fn configure(mut self, clap: &ArgMatches) -> anyhow::Result { self.program_file = clap.value_of("input").unwrap().to_string(); Ok(self) } } fn main() -> anyhow::Result<()> { let config = Config::init("crsn", "crsn.json5", env!("CARGO_PKG_VERSION"))?; info!("Loading {}", config.program_file); let source = read_file::read_file(&config.program_file)?; let parsers = Arc::new(vec![ ArithOps::new(), StackOps::new(), ScreenOps::new(), ]); let parsed = crsn::asm::assemble(&source, parsers)?; info!("Start runtime"); let thread = RunThread::new( ThreadToken(0), None, parsed.clone(), Addr(0), // TODO find "main"? &[], // TODO from CLI? ); let a = thread.start(); // ... let _ = a.join(); info!("Runtime shut down."); Ok(()) }