diff --git a/benchmarks/turnt_brilirs.toml b/benchmarks/turnt_brilirs.toml index b6f63b08c..5cb0969a3 100644 --- a/benchmarks/turnt_brilirs.toml +++ b/benchmarks/turnt_brilirs.toml @@ -1,3 +1,3 @@ -command = "bril2json < {filename} | cargo +nightly run --manifest-path ../brilirs/Cargo.toml --quiet -- -p {args}" +command = "bril2json < {filename} | cargo run --manifest-path ../brilirs/Cargo.toml --quiet -- -p {args}" output.out = "-" output.prof = "2" \ No newline at end of file diff --git a/bril-rs/src/lib.rs b/bril-rs/src/lib.rs index 6f84d29f8..4384cfc2d 100644 --- a/bril-rs/src/lib.rs +++ b/bril-rs/src/lib.rs @@ -1,3 +1,10 @@ +#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)] +// todo these are allowed to appease clippy but should be addressed some day +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] +#![allow(clippy::cargo_common_metadata)] + use std::fmt::{self, Display, Formatter}; use std::io::{self, Write}; @@ -10,7 +17,7 @@ pub struct Program { impl Display for Program { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - for func in self.functions.iter() { + for func in &self.functions { writeln!(f, "{}", func)?; } Ok(()) @@ -46,7 +53,7 @@ impl Display for Function { write!(f, ": {}", tpe)?; } writeln!(f, " {{")?; - for instr in self.instrs.iter() { + for instr in &self.instrs { writeln!(f, "{}", instr)?; } write!(f, "}}")?; @@ -331,7 +338,7 @@ pub enum Type { Float, #[cfg(feature = "memory")] #[serde(rename = "ptr")] - Pointer(Box), + Pointer(Box), } impl Display for Type { @@ -368,7 +375,7 @@ impl Display for Literal { } impl Literal { - pub fn get_type(&self) -> Type { + pub const fn get_type(&self) -> Type { match self { Literal::Int(_) => Type::Int, Literal::Bool(_) => Type::Bool, diff --git a/brilirs/Makefile b/brilirs/Makefile index 85687bb02..994434470 100644 --- a/brilirs/Makefile +++ b/brilirs/Makefile @@ -14,7 +14,7 @@ benchmark: .PHONY: release release: - RUSTFLAGS="-C target-cpu=native" cargo +nightly build --release + RUSTFLAGS="-C target-cpu=native" cargo build --release .PHONY: compare compare: release @@ -26,4 +26,4 @@ compare: release # This is primarily used for running examples and debuging a bril program .PHONY: example example: - bril2json < ../benchmarks/sqrt.bril | cargo +nightly run \ No newline at end of file + bril2json < ../benchmarks/sqrt.bril | cargo run \ No newline at end of file diff --git a/brilirs/src/basic_block.rs b/brilirs/src/basic_block.rs index c66e89cc5..6563282d0 100644 --- a/brilirs/src/basic_block.rs +++ b/brilirs/src/basic_block.rs @@ -11,9 +11,9 @@ pub struct BBProgram { } impl BBProgram { - pub fn new(prog: Program) -> Result { + pub fn new(prog: Program) -> Result { let num_funcs = prog.functions.len(); - let bb = BBProgram { + let bb = Self { func_index: prog .functions .into_iter() @@ -44,8 +44,8 @@ pub struct BasicBlock { } impl BasicBlock { - fn new() -> BasicBlock { - BasicBlock { + const fn new() -> Self { + Self { label: None, instrs: Vec::new(), numified_instrs: Vec::new(), @@ -83,18 +83,18 @@ impl NumifiedInstruction { num_var_map: &mut FxHashMap, ) -> Self { match instr { - Instruction::Constant { dest, .. } => NumifiedInstruction { + Instruction::Constant { dest, .. } => Self { dest: Some(get_num_from_map(dest, num_of_vars, num_var_map)), args: Vec::new(), }, - Instruction::Value { dest, args, .. } => NumifiedInstruction { + Instruction::Value { dest, args, .. } => Self { dest: Some(get_num_from_map(dest, num_of_vars, num_var_map)), args: args .iter() .map(|v| get_num_from_map(v, num_of_vars, num_var_map)) .collect(), }, - Instruction::Effect { args, .. } => NumifiedInstruction { + Instruction::Effect { args, .. } => Self { dest: None, args: args .iter() @@ -119,13 +119,13 @@ pub struct BBFunction { } impl BBFunction { - pub fn new(f: Function) -> BBFunction { - let (mut func, label_map) = BBFunction::find_basic_blocks(f); + pub fn new(f: Function) -> Self { + let (mut func, label_map) = Self::find_basic_blocks(f); func.build_cfg(label_map); func } - fn find_basic_blocks(func: bril_rs::Function) -> (BBFunction, FxHashMap) { + fn find_basic_blocks(func: bril_rs::Function) -> (Self, FxHashMap) { let mut blocks = Vec::new(); let mut label_map = FxHashMap::default(); @@ -197,7 +197,7 @@ impl BBFunction { } ( - BBFunction { + Self { name: func.name, args: func.args, return_type: func.return_type, diff --git a/brilirs/src/check.rs b/brilirs/src/check.rs index c1a1ba875..5ec254322 100644 --- a/brilirs/src/check.rs +++ b/brilirs/src/check.rs @@ -8,7 +8,7 @@ use crate::error::InterpError; use fxhash::FxHashMap; #[inline(always)] -fn check_num_args(expected: usize, args: &[String]) -> Result<(), InterpError> { +const fn check_num_args(expected: usize, args: &[String]) -> Result<(), InterpError> { if expected != args.len() { Err(InterpError::BadNumArgs(expected, args.len())) } else { @@ -17,7 +17,7 @@ fn check_num_args(expected: usize, args: &[String]) -> Result<(), InterpError> { } #[inline(always)] -fn check_num_funcs(expected: usize, funcs: &[String]) -> Result<(), InterpError> { +const fn check_num_funcs(expected: usize, funcs: &[String]) -> Result<(), InterpError> { if expected != funcs.len() { Err(InterpError::BadNumFuncs(expected, funcs.len())) } else { @@ -26,7 +26,7 @@ fn check_num_funcs(expected: usize, funcs: &[String]) -> Result<(), InterpError> } #[inline(always)] -fn check_num_labels(expected: usize, labels: &[String]) -> Result<(), InterpError> { +const fn check_num_labels(expected: usize, labels: &[String]) -> Result<(), InterpError> { if expected != labels.len() { Err(InterpError::BadNumLabels(expected, labels.len())) } else { @@ -50,7 +50,7 @@ fn update_env<'a>( typ: &'a Type, ) -> Result<(), InterpError> { match env.get(dest) { - Some(current_typ) => check_asmt_type(current_typ, &typ), + Some(current_typ) => check_asmt_type(current_typ, typ), None => { env.insert(dest, typ); Ok(()) @@ -76,7 +76,7 @@ fn get_type<'a>( #[inline(always)] fn get_ptr_type(typ: &bril_rs::Type) -> Result<&bril_rs::Type, InterpError> { match typ { - bril_rs::Type::Pointer(ptr_type) => Ok(&ptr_type), + bril_rs::Type::Pointer(ptr_type) => Ok(ptr_type), _ => Err(InterpError::ExpectedPointerType(typ.clone())), } } @@ -231,15 +231,15 @@ fn type_check_instruction<'a>( .zip(callee_func.args.iter()) .try_for_each(|(arg_name, expected_arg)| { let ty = env - .get(&arg_name as &str) + .get(arg_name as &str) .ok_or_else(|| InterpError::VarUndefined(arg_name.to_string()))?; - check_asmt_type(&ty, &expected_arg.arg_type) + check_asmt_type(ty, &expected_arg.arg_type) })?; match &callee_func.return_type { None => Err(InterpError::NonEmptyRetForfunc(callee_func.name.clone())), - Some(t) => check_asmt_type(op_type, &t), + Some(t) => check_asmt_type(op_type, t), }?; update_env(env, dest, op_type) } @@ -399,7 +399,7 @@ fn type_check_instruction<'a>( .zip(callee_func.args.iter()) .try_for_each(|(arg_name, expected_arg)| { let ty = env - .get(&arg_name as &str) + .get(arg_name as &str) .ok_or_else(|| InterpError::VarUndefined(arg_name.to_string()))?; check_asmt_type(ty, &expected_arg.arg_type) diff --git a/brilirs/src/interp.rs b/brilirs/src/interp.rs index 73ae49182..92c6e93b0 100644 --- a/brilirs/src/interp.rs +++ b/brilirs/src/interp.rs @@ -19,7 +19,7 @@ struct Environment { impl Environment { #[inline(always)] pub fn new(size: u32) -> Self { - Environment { + Self { env: vec![Value::default(); size as usize], } } @@ -43,7 +43,7 @@ struct Heap { impl Default for Heap { fn default() -> Self { - Heap { + Self { memory: FxHashMap::with_capacity_and_hasher(20, fxhash::FxBuildHasher::default()), base_num_counter: 0, } @@ -127,7 +127,7 @@ pub enum Value { impl Default for Value { fn default() -> Self { - Value::Uninitialized + Self::Uninitialized } } @@ -138,8 +138,8 @@ pub struct Pointer { } impl Pointer { - fn add(&self, offset: i64) -> Pointer { - Pointer { + const fn add(&self, offset: i64) -> Self { + Self { base: self.base, offset: self.offset + offset, } @@ -161,22 +161,22 @@ impl fmt::Display for Value { impl From<&bril_rs::Literal> for Value { #[inline(always)] - fn from(l: &bril_rs::Literal) -> Value { + fn from(l: &bril_rs::Literal) -> Self { match l { - bril_rs::Literal::Int(i) => Value::Int(*i), - bril_rs::Literal::Bool(b) => Value::Bool(*b), - bril_rs::Literal::Float(f) => Value::Float(*f), + bril_rs::Literal::Int(i) => Self::Int(*i), + bril_rs::Literal::Bool(b) => Self::Bool(*b), + bril_rs::Literal::Float(f) => Self::Float(*f), } } } impl From for Value { #[inline(always)] - fn from(l: bril_rs::Literal) -> Value { + fn from(l: bril_rs::Literal) -> Self { match l { - bril_rs::Literal::Int(i) => Value::Int(i), - bril_rs::Literal::Bool(b) => Value::Bool(b), - bril_rs::Literal::Float(f) => Value::Float(f), + bril_rs::Literal::Int(i) => Self::Int(i), + bril_rs::Literal::Bool(b) => Self::Bool(b), + bril_rs::Literal::Float(f) => Self::Float(f), } } } @@ -242,7 +242,7 @@ fn execute_value_op<'a, T: std::io::Write>( out: &mut T, value_store: &mut Environment, heap: &mut Heap, - last_label: &Option<&String>, + last_label: Option<&String>, instruction_count: &mut u32, ) -> Result<(), InterpError> { use bril_rs::ValueOps::*; @@ -536,7 +536,7 @@ fn execute<'a, T: std::io::Write>( value_store.set(numified_code.dest.unwrap(), Value::Float(*f)) } // this is safe because we type check this beforehand - _ => unsafe { unreachable_unchecked() }, + bril_rs::Literal::Bool(_) => unsafe { unreachable_unchecked() }, } } else { value_store.set(numified_code.dest.unwrap(), Value::from(value)); @@ -560,7 +560,7 @@ fn execute<'a, T: std::io::Write>( out, &mut value_store, heap, - &last_label, + last_label, instruction_count, )?; } @@ -576,7 +576,7 @@ fn execute<'a, T: std::io::Write>( op, &numified_code.args, funcs, - &curr_block, + curr_block, out, &value_store, heap, @@ -598,7 +598,7 @@ fn parse_args( mut env: Environment, args: &[bril_rs::Argument], args_as_nums: &[u32], - inputs: Vec<&str>, + inputs: &[&str], ) -> Result { if args.is_empty() && inputs.is_empty() { Ok(env) @@ -615,7 +615,7 @@ fn parse_args( Err(_) => { return Err(InterpError::BadFuncArgType( bril_rs::Type::Bool, - inputs.get(index).unwrap().to_string(), + (*inputs.get(index).unwrap()).to_string(), )) } Ok(b) => env.set(*arg_as_num, Value::Bool(b)), @@ -627,7 +627,7 @@ fn parse_args( Err(_) => { return Err(InterpError::BadFuncArgType( bril_rs::Type::Int, - inputs.get(index).unwrap().to_string(), + (*inputs.get(index).unwrap()).to_string(), )) } Ok(i) => env.set(*arg_as_num, Value::Int(i)), @@ -639,7 +639,7 @@ fn parse_args( Err(_) => { return Err(InterpError::BadFuncArgType( bril_rs::Type::Float, - inputs.get(index).unwrap().to_string(), + (*inputs.get(index).unwrap()).to_string(), )) } Ok(f) => env.set(*arg_as_num, Value::Float(f)), @@ -654,9 +654,9 @@ fn parse_args( } pub fn execute_main( - prog: BBProgram, + prog: &BBProgram, mut out: T, - input_args: Vec<&str>, + input_args: &[&str], profiling: bool, ) -> Result<(), InterpError> { let main_func = prog.get("main").ok_or(InterpError::NoMainFunction)?; @@ -673,8 +673,8 @@ pub fn execute_main( let mut instruction_count = 0; execute( - &prog, - &main_func, + prog, + main_func, &mut out, value_store, &mut heap, diff --git a/brilirs/src/lib.rs b/brilirs/src/lib.rs index eabb6f55c..28283df77 100644 --- a/brilirs/src/lib.rs +++ b/brilirs/src/lib.rs @@ -1,4 +1,9 @@ -#![feature(or_patterns)] +// The group clippy::pedantic is not used as it ends up being more annoying than useful +#![warn(clippy::all, clippy::nursery, clippy::cargo)] +// todo these are allowed to appease clippy but should be addressed some day +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::cargo_common_metadata)] +#![allow(clippy::too_many_arguments)] use error::InterpError; @@ -8,19 +13,19 @@ mod error; mod interp; pub fn run_input( - input: Box, - out: T, - input_args: Vec<&str>, - profiling: bool, - check: bool, + input: Box, + out: T, + input_args: Vec<&str>, + profiling: bool, + check: bool, ) -> Result<(), InterpError> { - let prog = bril_rs::load_program_from_read(input); - let bbprog = basic_block::BBProgram::new(prog)?; - check::type_check(&bbprog)?; + let prog = bril_rs::load_program_from_read(input); + let bbprog = basic_block::BBProgram::new(prog)?; + check::type_check(&bbprog)?; - if !check { - interp::execute_main(bbprog, out, input_args, profiling)?; - } + if !check { + interp::execute_main(&bbprog, out, &input_args, profiling)?; + } - Ok(()) + Ok(()) } diff --git a/docs/tools/brilirs.md b/docs/tools/brilirs.md index a873c9b34..b36d2eb3d 100644 --- a/docs/tools/brilirs.md +++ b/docs/tools/brilirs.md @@ -2,18 +2,18 @@ Fast Interpreter in Rust ======================== The `brilirs` directory contains a fast Bril interpreter written in [Rust][]. -It is a drop-in replacement for the [reference interpreter](interp.md) that prioritizes speed over completeness and hacakability. +It is a drop-in replacement for the [reference interpreter](interp.md) that prioritizes speed over completeness and hackability. It implements [core Bril](../lang/core.md) and the [SSA][], [memory][], and [floating point][float] extensions. Read [more about the implementation][blog], which is originally by Wil Thomason and Daniel Glus. Install ------- -To use `brilirs` you will need to [install Rust](https://www.rust-lang.org/tools/install) and add the nightly channel with `rustup toolchain install nightly`. Use `echo $PATH` to check that `$HOME/.cargo/bin` is on your [path](https://unix.stackexchange.com/a/26059/61192). +To use `brilirs` you will need to [install Rust](https://www.rust-lang.org/tools/install). Use `echo $PATH` to check that `$HOME/.cargo/bin` is on your [path](https://unix.stackexchange.com/a/26059/61192). In the `brilirs` directory, build the interpreter with: - cargo +nightly install --path . + cargo install --path . Run a program by piping a JSON Bril program into it: diff --git a/test/fail/turnt_brilirs.toml b/test/fail/turnt_brilirs.toml index 9b753d391..488152731 100644 --- a/test/fail/turnt_brilirs.toml +++ b/test/fail/turnt_brilirs.toml @@ -1,2 +1,2 @@ -command = "bril2json < {filename} | cargo +nightly run --manifest-path ../../brilirs/Cargo.toml -- {args}" +command = "bril2json < {filename} | cargo run --manifest-path ../../brilirs/Cargo.toml -- {args}" return_code = 2 \ No newline at end of file diff --git a/test/interp-error/turnt_brilirs.toml b/test/interp-error/turnt_brilirs.toml index 611c7d63a..8217b69a6 100644 --- a/test/interp-error/turnt_brilirs.toml +++ b/test/interp-error/turnt_brilirs.toml @@ -1,3 +1,3 @@ -command = "bril2json < {filename} | cargo +nightly run --manifest-path ../../brilirs/Cargo.toml -- {args}" +command = "bril2json < {filename} | cargo run --manifest-path ../../brilirs/Cargo.toml -- {args}" return_code = 2 output.err = "2" \ No newline at end of file diff --git a/test/interp/turnt_brilirs.toml b/test/interp/turnt_brilirs.toml index 985b2d5cd..c435d630a 100644 --- a/test/interp/turnt_brilirs.toml +++ b/test/interp/turnt_brilirs.toml @@ -1 +1 @@ -command = "bril2json < {filename} | cargo +nightly run --manifest-path ../../brilirs/Cargo.toml -- {args}" +command = "bril2json < {filename} | cargo run --manifest-path ../../brilirs/Cargo.toml -- {args}" diff --git a/test/mem/turnt_brilirs.toml b/test/mem/turnt_brilirs.toml index 985b2d5cd..c435d630a 100644 --- a/test/mem/turnt_brilirs.toml +++ b/test/mem/turnt_brilirs.toml @@ -1 +1 @@ -command = "bril2json < {filename} | cargo +nightly run --manifest-path ../../brilirs/Cargo.toml -- {args}" +command = "bril2json < {filename} | cargo run --manifest-path ../../brilirs/Cargo.toml -- {args}"