use clap::Parser; use codespan_reporting::diagnostic::Label; use codespan_reporting::files::SimpleFiles; use codespan_reporting::term; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; use dm_std_lib::add_all_std_core; use dmc_lib::constants_table::ConstantsTable; use dmc_lib::diagnostic::Diagnostic; use dmc_lib::parser::parse_compilation_unit; use dmc_lib::symbol_table::SymbolTable; use dvm_lib::vm::constant::{Constant, StringConstant}; use dvm_lib::vm::value::Value; use dvm_lib::vm::{CallStack, DvmContext, call}; use std::path::PathBuf; use std::rc::Rc; #[derive(Debug, Parser)] #[command(name = "dm", about = "Deimos", version = "0.1.0", long_about = None)] struct Cli { script: PathBuf, #[arg(long)] show_asm: bool, } fn main() { let args = Cli::parse(); let input = std::fs::read_to_string(&args.script).unwrap(); let mut files: SimpleFiles<&str, &str> = SimpleFiles::new(); let script_file_id = files.add(args.script.to_str().unwrap(), &input); let parse_result = parse_compilation_unit(&input); let mut compilation_unit = match parse_result { Ok(compilation_unit) => compilation_unit, Err(diagnostics) => { check_and_report_diagnostics(&files, script_file_id, &diagnostics); unreachable!(); } }; let mut symbol_table = SymbolTable::new(); let gather_names_diagnostics = compilation_unit.gather_declared_names(&mut symbol_table); check_and_report_diagnostics(&files, script_file_id, &gather_names_diagnostics); let name_usages_diagnostics = compilation_unit.check_name_usages(&symbol_table); check_and_report_diagnostics(&files, script_file_id, &name_usages_diagnostics); let type_check_diagnostics = compilation_unit.type_check(&symbol_table); check_and_report_diagnostics(&files, script_file_id, &type_check_diagnostics); let mut constants_table = ConstantsTable::new(); let asm_functions = compilation_unit.assemble(&symbol_table, &mut constants_table); if args.show_asm { for asm_function in &asm_functions { println!("{:#?}", asm_function); } } let mut dvm_context = DvmContext::new(); // add std::core fns add_all_std_core(&mut dvm_context); for asm_function in &asm_functions { let function = asm_function.dvm(); dvm_context.add_function(function); } for (name, content) in &constants_table.string_constants() { dvm_context.add_constant(Constant::String(StringConstant::new( Rc::from(name.clone()), content.as_str(), ))); } let mut registers: Vec = vec![]; let mut call_stack = CallStack::new(); let result = call( &dvm_context, &mut registers, &mut call_stack, "main", vec![], ); println!("{:?}", result); } fn check_and_report_diagnostics( files: &SimpleFiles<&str, &str>, script_file_id: usize, diagnostics: &[Diagnostic], ) { if !diagnostics.is_empty() { let writer = StandardStream::stderr(ColorChoice::Always); let config = term::Config::default(); for diagnostic in diagnostics { let csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error() .with_message(diagnostic.message()) .with_label(Label::primary( script_file_id, diagnostic.start()..diagnostic.end(), )); term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap(); } if diagnostics.len() == 1 { eprintln!("There was 1 diagnostic. See above for more information."); } else { eprintln!( "There were {} diagnostics. See above for more information.", diagnostics.len() ); } std::process::exit(1); } }