diff --git a/bril-rs/src/conversion.rs b/bril-rs/src/conversion.rs index 8df7e57d..31358e88 100644 --- a/bril-rs/src/conversion.rs +++ b/bril-rs/src/conversion.rs @@ -2,15 +2,16 @@ use std::fmt::Display; use crate::{ AbstractArgument, AbstractCode, AbstractFunction, AbstractInstruction, AbstractProgram, - AbstractType, Argument, Code, EffectOps, Function, Instruction, Position, Program, Type, - ValueOps, + AbstractType, Argument, Code, Function, Instruction, Position, Program, Type, }; use thiserror::Error; -// This is a nifty trick to supply a global value for pos when it is not defined #[cfg(not(feature = "position"))] -#[allow(non_upper_case_globals)] +#[expect( + non_upper_case_globals, + reason = "This is a nifty trick to supply a global value for pos when it is not defined" +)] const pos: Option = None; /// This is the [`std::error::Error`] implementation for `bril_rs`. This crate currently only supports errors from converting between [`AbstractProgram`] and [Program] @@ -213,66 +214,7 @@ impl TryFrom for Instruction { .map_err(|e: ConversionError| e.add_pos(pos.clone()))?, #[cfg(feature = "position")] pos: pos.clone(), - op: match op.as_ref() { - "add" => ValueOps::Add, - "mul" => ValueOps::Mul, - "div" => ValueOps::Div, - "eq" => ValueOps::Eq, - "lt" => ValueOps::Lt, - "gt" => ValueOps::Gt, - "le" => ValueOps::Le, - "ge" => ValueOps::Ge, - "not" => ValueOps::Not, - "and" => ValueOps::And, - "or" => ValueOps::Or, - "call" => ValueOps::Call, - "id" => ValueOps::Id, - "sub" => ValueOps::Sub, - #[cfg(feature = "ssa")] - "phi" => ValueOps::Phi, - #[cfg(feature = "float")] - "fadd" => ValueOps::Fadd, - #[cfg(feature = "float")] - "fsub" => ValueOps::Fsub, - #[cfg(feature = "float")] - "fmul" => ValueOps::Fmul, - #[cfg(feature = "float")] - "fdiv" => ValueOps::Fdiv, - #[cfg(feature = "float")] - "feq" => ValueOps::Feq, - #[cfg(feature = "float")] - "flt" => ValueOps::Flt, - #[cfg(feature = "float")] - "fgt" => ValueOps::Fgt, - #[cfg(feature = "float")] - "fle" => ValueOps::Fle, - #[cfg(feature = "float")] - "fge" => ValueOps::Fge, - #[cfg(feature = "char")] - "ceq" => ValueOps::Ceq, - #[cfg(feature = "char")] - "clt" => ValueOps::Clt, - #[cfg(feature = "char")] - "cgt" => ValueOps::Cgt, - #[cfg(feature = "char")] - "cle" => ValueOps::Cle, - #[cfg(feature = "char")] - "cge" => ValueOps::Cge, - #[cfg(feature = "char")] - "char2int" => ValueOps::Char2int, - #[cfg(feature = "char")] - "int2char" => ValueOps::Int2char, - #[cfg(feature = "memory")] - "alloc" => ValueOps::Alloc, - #[cfg(feature = "memory")] - "load" => ValueOps::Load, - #[cfg(feature = "memory")] - "ptradd" => ValueOps::PtrAdd, - v => { - return Err(ConversionError::InvalidValueOps(v.to_string())) - .map_err(|e| e.add_pos(pos)) - } - }, + op: op.parse().map_err(|e: ConversionError| e.add_pos(pos))?, }, AbstractInstruction::Effect { args, @@ -287,28 +229,7 @@ impl TryFrom for Instruction { labels, #[cfg(feature = "position")] pos: pos.clone(), - op: match op.as_ref() { - "jmp" => EffectOps::Jump, - "br" => EffectOps::Branch, - "call" => EffectOps::Call, - "ret" => EffectOps::Return, - "print" => EffectOps::Print, - "nop" => EffectOps::Nop, - #[cfg(feature = "memory")] - "store" => EffectOps::Store, - #[cfg(feature = "memory")] - "free" => EffectOps::Free, - #[cfg(feature = "speculate")] - "speculate" => EffectOps::Speculate, - #[cfg(feature = "speculate")] - "commit" => EffectOps::Commit, - #[cfg(feature = "speculate")] - "guard" => EffectOps::Guard, - e => { - return Err(ConversionError::InvalidEffectOps(e.to_string())) - .map_err(|e| e.add_pos(pos)) - } - }, + op: op.parse().map_err(|e: ConversionError| e.add_pos(pos))?, }, }) } @@ -325,21 +246,15 @@ impl TryFrom> for Type { impl TryFrom for Type { type Error = ConversionError; fn try_from(value: AbstractType) -> Result { - Ok(match value { - AbstractType::Primitive(t) if t == "int" => Self::Int, - AbstractType::Primitive(t) if t == "bool" => Self::Bool, - #[cfg(feature = "float")] - AbstractType::Primitive(t) if t == "float" => Self::Float, - #[cfg(feature = "char")] - AbstractType::Primitive(t) if t == "char" => Self::Char, - AbstractType::Primitive(t) => return Err(ConversionError::InvalidPrimitive(t)), + match value { + AbstractType::Primitive(t) => t.parse(), #[cfg(feature = "memory")] AbstractType::Parameterized(t, ty) if t == "ptr" => { - Self::Pointer(Box::new((*ty).try_into()?)) + Ok(Self::Pointer(Box::new((*ty).try_into()?))) } AbstractType::Parameterized(t, ty) => { - return Err(ConversionError::InvalidParameterized(t, ty.to_string())) + Err(ConversionError::InvalidParameterized(t, ty.to_string())) } - }) + } } } diff --git a/bril-rs/src/lib.rs b/bril-rs/src/lib.rs index 8b3048b9..5b5e9b77 100644 --- a/bril-rs/src/lib.rs +++ b/bril-rs/src/lib.rs @@ -2,7 +2,6 @@ #![warn(missing_docs)] #![warn(clippy::allow_attributes)] #![doc = include_str!("../README.md")] -#![allow(clippy::too_many_lines)] /// Provides the unstructured representation of Bril programs pub mod abstract_program; diff --git a/bril-rs/src/program.rs b/bril-rs/src/program.rs index eccf355f..4aca0340 100644 --- a/bril-rs/src/program.rs +++ b/bril-rs/src/program.rs @@ -1,10 +1,13 @@ use std::{ fmt::{self, Display, Formatter}, hash::Hash, + str::FromStr, }; use serde::{Deserialize, Serialize}; +use crate::conversion::ConversionError; + /// Equivalent to a file of bril code #[cfg_attr(not(feature = "float"), derive(Eq))] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] @@ -389,6 +392,32 @@ impl Display for EffectOps { } } +impl FromStr for EffectOps { + type Err = ConversionError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "jmp" => Self::Jump, + "br" => Self::Branch, + "call" => Self::Call, + "ret" => Self::Return, + "print" => Self::Print, + "nop" => Self::Nop, + #[cfg(feature = "memory")] + "store" => Self::Store, + #[cfg(feature = "memory")] + "free" => Self::Free, + #[cfg(feature = "speculate")] + "speculate" => Self::Speculate, + #[cfg(feature = "speculate")] + "commit" => Self::Commit, + #[cfg(feature = "speculate")] + "guard" => Self::Guard, + e => Err(ConversionError::InvalidEffectOps(e.to_string()))?, + }) + } +} + /// #[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[serde(rename_all = "lowercase")] @@ -544,6 +573,70 @@ impl Display for ValueOps { } } +impl FromStr for ValueOps { + type Err = ConversionError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "add" => Self::Add, + "mul" => Self::Mul, + "div" => Self::Div, + "eq" => Self::Eq, + "lt" => Self::Lt, + "gt" => Self::Gt, + "le" => Self::Le, + "ge" => Self::Ge, + "not" => Self::Not, + "and" => Self::And, + "or" => Self::Or, + "call" => Self::Call, + "id" => Self::Id, + "sub" => Self::Sub, + #[cfg(feature = "ssa")] + "phi" => Self::Phi, + #[cfg(feature = "float")] + "fadd" => Self::Fadd, + #[cfg(feature = "float")] + "fsub" => Self::Fsub, + #[cfg(feature = "float")] + "fmul" => Self::Fmul, + #[cfg(feature = "float")] + "fdiv" => Self::Fdiv, + #[cfg(feature = "float")] + "feq" => Self::Feq, + #[cfg(feature = "float")] + "flt" => Self::Flt, + #[cfg(feature = "float")] + "fgt" => Self::Fgt, + #[cfg(feature = "float")] + "fle" => Self::Fle, + #[cfg(feature = "float")] + "fge" => Self::Fge, + #[cfg(feature = "char")] + "ceq" => Self::Ceq, + #[cfg(feature = "char")] + "clt" => Self::Clt, + #[cfg(feature = "char")] + "cgt" => Self::Cgt, + #[cfg(feature = "char")] + "cle" => Self::Cle, + #[cfg(feature = "char")] + "cge" => Self::Cge, + #[cfg(feature = "char")] + "char2int" => Self::Char2int, + #[cfg(feature = "char")] + "int2char" => Self::Int2char, + #[cfg(feature = "memory")] + "alloc" => Self::Alloc, + #[cfg(feature = "memory")] + "load" => Self::Load, + #[cfg(feature = "memory")] + "ptradd" => Self::PtrAdd, + v => Err(ConversionError::InvalidValueOps(v.to_string()))?, + }) + } +} + /// #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[serde(rename_all = "lowercase")] @@ -579,6 +672,22 @@ impl Display for Type { } } +impl FromStr for Type { + type Err = ConversionError; + + fn from_str(s: &str) -> Result { + match s { + "int" => Ok(Self::Int), + "bool" => Ok(Self::Bool), + #[cfg(feature = "float")] + "float" => Ok(Self::Float), + #[cfg(feature = "char")] + "char" => Ok(Self::Char), + _ => Err(ConversionError::InvalidPrimitive(s.to_string())), + } + } +} + /// A JSON number/value #[cfg_attr(not(feature = "float"), derive(Eq, Hash))] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]