diff --git a/cpr_bf/src/lib.rs b/cpr_bf/src/lib.rs index 6237f35..dd7b326 100644 --- a/cpr_bf/src/lib.rs +++ b/cpr_bf/src/lib.rs @@ -225,7 +225,7 @@ impl Display for VMB } } -impl +impl VMBuilder { /// Changes the type of the memory cells to `U` @@ -287,10 +287,10 @@ impl Box { log::info!("Building Brainfuck VM with configuration: {}", self); - Box::new(VirtualMachine::::new( + Box::new(VirtualMachine::::new( self.initial_size, - stdin(), - stdout(), + self.reader, + self.writer, )) } } diff --git a/cpr_bfvm/src/cli_args.rs b/cpr_bfvm/src/cli_args.rs index 1761942..a9aa0db 100644 --- a/cpr_bfvm/src/cli_args.rs +++ b/cpr_bfvm/src/cli_args.rs @@ -5,22 +5,36 @@ use clap::{Parser, ValueEnum}; #[derive(Parser, Debug)] #[command(author, about, version)] pub(crate) struct CLIArgs { + /// The file to run #[arg()] pub filename: PathBuf, + /// The file from which running programs take their input. Defaults to stdin if empty + #[arg(short, long)] + pub input: Option, + + /// The file to which running programs write their output. Defaults to stdout if empty + #[arg(short, long)] + pub output: Option, + + /// The size of each individual memory cell #[arg(value_enum, short, long, default_value_t = CellSize::U8)] pub cellsize: CellSize, + /// The amount of preallocated memory cells. If a static allocator is used, this is also the total amount of available memory #[arg(short, long, default_value_t = 16)] pub preallocated: usize, + /// The memory allocator to use #[arg(value_enum, short, long, default_value_t = Allocator::Dynamic)] pub allocator: Allocator, + /// The verbosity of the logger #[cfg(not(debug_assertions))] #[arg(value_enum, short, long, default_value_t = LogLevel::Warn)] pub verbosity: LogLevel, + /// The verbosity of the logger #[cfg(debug_assertions)] #[arg(value_enum, short, long, default_value_t = LogLevel::Info)] pub verbosity: LogLevel, diff --git a/cpr_bfvm/src/main.rs b/cpr_bfvm/src/main.rs index 047ff60..9e7893f 100644 --- a/cpr_bfvm/src/main.rs +++ b/cpr_bfvm/src/main.rs @@ -1,5 +1,6 @@ mod cli_args; +use std::fs::File; use std::process::ExitCode; use clap::Parser; @@ -9,7 +10,7 @@ use cpr_bf::VMBuilder; macro_rules! assign_allocator_and_build { ($args:expr, $builder:expr) => { - match $args { + match $args.allocator { cli_args::Allocator::Dynamic => $builder.with_allocator::().build(), cli_args::Allocator::StaticChecked => $builder .with_allocator::() @@ -21,32 +22,58 @@ macro_rules! assign_allocator_and_build { }; } +macro_rules! assign_cellsize_and_build { + ($args:expr, $builder:expr) => { + match $args.cellsize { + cli_args::CellSize::U8 => assign_allocator_and_build!($args, $builder.with_cell_type::()), + cli_args::CellSize::U16 => assign_allocator_and_build!($args, $builder.with_cell_type::()), + cli_args::CellSize::U32 => assign_allocator_and_build!($args, $builder.with_cell_type::()), + cli_args::CellSize::U64 => assign_allocator_and_build!($args, $builder.with_cell_type::()), + cli_args::CellSize::U128 => assign_allocator_and_build!($args, $builder.with_cell_type::()), + } + } +} + +macro_rules! assign_input_and_build { + ($args:expr, $builder:expr) => { + match $args.input { + Some(input) => { + assign_cellsize_and_build!($args, $builder.with_reader(File::open(input).expect("Could not open input file"))) + } + None => assign_cellsize_and_build!($args, $builder) + } + }; +} + +macro_rules! assign_output_and_build { + ($args:expr, $builder:expr) => { + match $args.output { + Some(output) => { + let output_file = File::options().create(true).truncate(true).write(true).open(output).expect("Could not open output file"); + assign_input_and_build!($args, $builder.with_writer(output_file)) + } + None => assign_input_and_build!($args, $builder) + } + }; +} + +macro_rules! process_args_and_build_vm { + ($args:expr) => { + { + let vm_builder = VMBuilder::new().with_preallocated_cells($args.preallocated); + assign_output_and_build!($args, vm_builder) + } + }; +} + fn main() -> ExitCode { let args = CLIArgs::parse(); simple_logger::init_with_level(args.verbosity.clone().into()).unwrap(); - + log::info!("Assigning VM options and building"); - let vm_builder = VMBuilder::new().with_preallocated_cells(args.preallocated); - - let mut vm = match args.cellsize { - cli_args::CellSize::U8 => { - assign_allocator_and_build!(args.allocator, vm_builder.with_cell_type::()) - } - cli_args::CellSize::U16 => { - assign_allocator_and_build!(args.allocator, vm_builder.with_cell_type::()) - } - cli_args::CellSize::U32 => { - assign_allocator_and_build!(args.allocator, vm_builder.with_cell_type::()) - } - cli_args::CellSize::U64 => { - assign_allocator_and_build!(args.allocator, vm_builder.with_cell_type::()) - } - cli_args::CellSize::U128 => { - assign_allocator_and_build!(args.allocator, vm_builder.with_cell_type::()) - } - }; + let mut vm = process_args_and_build_vm!(args); log::info!("Running program"); if let Err(e) = vm.run_from_path(&args.filename) {