From b88b230495fd5077cf94abc693e401e05c3a7db3 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Mon, 9 Mar 2026 20:22:27 -0500 Subject: [PATCH] Make run subcommand. --- dm/src/main.rs | 175 ++++++++----------------------------------------- dm/src/run.rs | 146 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 148 deletions(-) create mode 100644 dm/src/run.rs diff --git a/dm/src/main.rs b/dm/src/main.rs index ddd1dab..e5fadc9 100644 --- a/dm/src/main.rs +++ b/dm/src/main.rs @@ -1,163 +1,42 @@ -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::function::Function; -use dvm_lib::vm::value::Value; -use dvm_lib::vm::{CallStack, DvmContext, call}; +mod run; + +use crate::run::run; +use clap::{Parser, Subcommand}; use std::path::PathBuf; #[derive(Debug, Parser)] #[command(name = "dm", about = "Deimos", version = "0.1.0", long_about = None)] struct Cli { - script: PathBuf, + #[command(subcommand)] + sub_command: SubCommand, +} - #[arg(long)] - show_asm: bool, +#[derive(Debug, Subcommand)] +enum SubCommand { + Run { + script: PathBuf, - #[arg(long)] - show_ir: bool, + #[arg(long)] + show_asm: bool, - #[arg(long, default_value = "8")] - register_count: usize, + #[arg(long)] + show_ir: bool, + + #[arg(long, default_value = "8")] + register_count: usize, + }, } 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!(); + match &args.sub_command { + SubCommand::Run { + script, + show_asm, + show_ir, + register_count, + } => { + run(script, *show_asm, *show_ir, *register_count); } - }; - - let mut symbol_table = SymbolTable::new(); - - match compilation_unit.gather_declared_names(&mut symbol_table) { - Ok(_) => {} - Err(diagnostics) => { - report_and_exit(&diagnostics, script_file_id, &files); - } - } - - match compilation_unit.check_name_usages(&symbol_table) { - Ok(_) => {} - Err(diagnostics) => { - report_and_exit(&diagnostics, script_file_id, &files); - } - } - - match compilation_unit.type_check(&symbol_table) { - Ok(_) => {} - Err(diagnostics) => { - report_and_exit(&diagnostics, script_file_id, &files); - } - } - - let mut ir_functions = compilation_unit.to_ir(&symbol_table); - - if args.show_ir { - for ir_function in &ir_functions { - println!("{}", ir_function); - } - } - - let mut functions: Vec = vec![]; - let mut constants_table = ConstantsTable::new(); - - for ir_function in &mut ir_functions { - let (_, stack_size) = ir_function.assign_registers(args.register_count); - let function = ir_function.assemble(stack_size, &mut constants_table); - functions.push(function); - } - - if args.show_asm { - for function in &functions { - println!("{}", function); - } - } - - let mut dvm_context = DvmContext::new(); - - // add std::core fns - add_all_std_core(&mut dvm_context); - - for function in functions { - dvm_context - .functions_mut() - .insert(function.name_owned(), function); - } - - for (name, content) in &constants_table.string_constants() { - dvm_context.constants_mut().insert( - name.clone(), - Constant::String(StringConstant::new(name.clone(), content.clone())), - ); - } - - let mut registers: Vec = vec![Value::Null; args.register_count]; - let mut call_stack = CallStack::new(); - - let result = call( - &dvm_context, - &mut registers, - &mut call_stack, - "main", - &vec![], - ); - if let Some(value) = result { - println!("{}", value); } } - -fn check_and_report_diagnostics( - files: &SimpleFiles<&str, &str>, - script_file_id: usize, - diagnostics: &[Diagnostic], -) { - if !diagnostics.is_empty() { - report_and_exit(diagnostics, script_file_id, files); - } -} - -fn report_and_exit( - diagnostics: &[Diagnostic], - script_file_id: usize, - files: &SimpleFiles<&str, &str>, -) -> ! { - 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); -} diff --git a/dm/src/run.rs b/dm/src/run.rs new file mode 100644 index 0000000..df4414e --- /dev/null +++ b/dm/src/run.rs @@ -0,0 +1,146 @@ +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::function::Function; +use dvm_lib::vm::value::Value; +use dvm_lib::vm::{CallStack, DvmContext, call}; +use std::path::PathBuf; + +pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usize) { + let input = std::fs::read_to_string(script).unwrap(); + + let mut files: SimpleFiles<&str, &str> = SimpleFiles::new(); + let script_file_id = files.add(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(); + + match compilation_unit.gather_declared_names(&mut symbol_table) { + Ok(_) => {} + Err(diagnostics) => { + report_and_exit(&diagnostics, script_file_id, &files); + } + } + + match compilation_unit.check_name_usages(&symbol_table) { + Ok(_) => {} + Err(diagnostics) => { + report_and_exit(&diagnostics, script_file_id, &files); + } + } + + match compilation_unit.type_check(&symbol_table) { + Ok(_) => {} + Err(diagnostics) => { + report_and_exit(&diagnostics, script_file_id, &files); + } + } + + let mut ir_functions = compilation_unit.to_ir(&symbol_table); + + if show_ir { + for ir_function in &ir_functions { + println!("{}", ir_function); + } + } + + let mut functions: Vec = vec![]; + let mut constants_table = ConstantsTable::new(); + + for ir_function in &mut ir_functions { + let (_, stack_size) = ir_function.assign_registers(register_count); + let function = ir_function.assemble(stack_size, &mut constants_table); + functions.push(function); + } + + if show_asm { + for function in &functions { + println!("{}", function); + } + } + + let mut dvm_context = DvmContext::new(); + + // add std::core fns + add_all_std_core(&mut dvm_context); + + for function in functions { + dvm_context + .functions_mut() + .insert(function.name_owned(), function); + } + + for (name, content) in &constants_table.string_constants() { + dvm_context.constants_mut().insert( + name.clone(), + Constant::String(StringConstant::new(name.clone(), content.clone())), + ); + } + + let mut registers: Vec = vec![Value::Null; register_count]; + let mut call_stack = CallStack::new(); + + let result = call( + &dvm_context, + &mut registers, + &mut call_stack, + "main", + &vec![], + ); + if let Some(value) = result { + println!("{}", value); + } +} + +fn check_and_report_diagnostics( + files: &SimpleFiles<&str, &str>, + script_file_id: usize, + diagnostics: &[Diagnostic], +) { + if !diagnostics.is_empty() { + report_and_exit(diagnostics, script_file_id, files); + } +} + +fn report_and_exit( + diagnostics: &[Diagnostic], + script_file_id: usize, + files: &SimpleFiles<&str, &str>, +) -> ! { + 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); +}