use std::fs; use std::path::PathBuf; use serde::Deserialize; /// Additive less than. Updates probability after comparing pub fn a_lt(p: &mut f64, additive: f64) -> bool { let is_lt = *p < additive; *p -= additive; is_lt } // Makes all these structs public and deserializable macro_rules! toml_struct { (struct $name:ident {$($field:ident: $t:ty,)*}) => { #[derive(Deserialize, Clone)] pub struct $name { $(pub $field: $t),* } } } toml_struct!{ struct Params { verify_config: bool, global_flow: GlobalFlow, statements: Statments, types: Types, dev: Dev, } } impl Params { pub fn parse(p: &PathBuf) -> Self { let file_string = fs::read_to_string(p) .expect("Failed to read parameters file into string"); let params: Params = toml::from_str(&file_string) .expect("Failed to parse TOML from parameters file"); params } pub fn verify(&self) -> Result<(), String> { let global_flow = self.global_flow.verify(); let statements = self.statements.verify(); let types = self.types.verify(); let dev = self.dev.verify(); if global_flow.is_err() { global_flow } else if statements.is_err() { statements } else if types.is_err() { types } else if dev.is_err() { dev } else { Ok(()) } } } toml_struct!{ struct GlobalFlow { gen_decl: f64, gen_subroutine: f64, gen_typedef: f64, end_generation: f64, } } impl GlobalFlow { fn verify(&self) -> Result<(), String> { let sum = self.gen_decl + self.gen_subroutine + self.gen_typedef + self.end_generation; if (sum - 1.0).abs() > f64::EPSILON { Err(format!("global_flow probability sum is = {}", sum)) } else { Ok(()) } } } toml_struct!{ struct Statments { gen_assign: GenAssign, gen_decl: GenDecl, gen_global_decl: GenGlobalDecl, gen_if_statement: GenIfStatement, gen_loop: GenLoop, } } impl Statments { fn verify(&self) -> Result<(), String> { let gen_assign = self.gen_assign.verify(); let gen_decl = self.gen_decl.verify(); let gen_global_decl = self.gen_global_decl.verify(); let gen_if_statement = self.gen_if_statement.verify(); let gen_loop = self.gen_loop.verify(); if gen_assign.is_err() { gen_assign } else if gen_decl.is_err() { gen_decl } else if gen_global_decl.is_err() { gen_global_decl } else if gen_if_statement.is_err() { gen_if_statement } else if gen_loop.is_err() { gen_loop } else { Ok(()) } } } toml_struct!{ struct GenAssign { gen_boolean: f64, gen_character: f64, gen_integer: f64, gen_real: f64, gen_tuple: f64, } } impl GenAssign { fn verify(&self) -> Result<(), String> { Ok(()) } } toml_struct!{ struct GenDecl { gen_boolean: f64, gen_character: f64, gen_integer: f64, gen_real: f64, gen_tuple: f64, qual_const: f64, qual_var: f64, } } impl GenDecl { fn verify(&self) -> Result<(), String> { let sum_type = self.gen_boolean + self.gen_character + self.gen_integer + self.gen_real + self.gen_tuple; let sum_qual = self.qual_const + self.qual_var; if (sum_type - 1.0).abs() > f64::EPSILON { Err(format!("statements.gen_decl probability sum for types is = {}", sum_type)) } else if (sum_qual - 1.0).abs() > f64::EPSILON { Err(format!("statements.gen_decl probability sum for qualifiers is = {}", sum_qual)) } else { Ok(()) } } } toml_struct!{ struct GenGlobalDecl { gen_boolean: f64, gen_character: f64, gen_integer: f64, gen_real: f64, gen_tuple: f64, } } impl GenGlobalDecl { fn verify(&self) -> Result<(), String> { Ok(()) } } toml_struct!{ struct GenIfStatement { gen_statement: f64, end_gen_statement: f64, fork_elif: f64, fork_else: f64, fork_end: f64, } } impl GenIfStatement { fn verify(&self) -> Result<(), String> { Ok(()) } } toml_struct!{ struct GenLoop { gen_inf_loop: f64, gen_cond_loop: f64, gen_statement: f64, end_gen_statement: f64, } } impl GenLoop { fn verify(&self) -> Result<(), String> { Ok(()) } } toml_struct!{ struct Types { gen_boolean: GenBoolean, gen_integer: GenInteger, gen_real: GenReal, } } impl Types { fn verify(&self) -> Result<(), String> { let gen_boolean = self.gen_boolean.verify(); let gen_integer = self.gen_integer.verify(); let gen_real = self.gen_real.verify(); if gen_boolean.is_err() { gen_boolean } else if gen_integer.is_err() { gen_integer } else if gen_real.is_err() { gen_real } else { Ok(()) } } } toml_struct!{ struct GenBoolean { expr_and: f64, expr_or: f64, expr_not: f64, expr_gt: f64, expr_ge: f64, expr_lt: f64, expr_le: f64, expr_eq: f64, expr_eq_real: f64, expr_eq_char: f64, expr_eq_tuple: f64, expr_ne: f64, expr_ne_real: f64, expr_ne_char: f64, expr_ne_tuple: f64, get_instant: f64, } } impl GenBoolean { fn verify(&self) -> Result<(), String> { Ok(()) } } toml_struct!{ struct GenInteger { expr_add: f64, expr_sub: f64, expr_mul: f64, expr_div: f64, expr_rem: f64, expr_exp: f64, expr_pos: f64, expr_neg: f64, get_instant: f64, max_depth: u32, } } impl GenInteger { fn verify(&self) -> Result<(), String> { let sum = self.expr_add + self.expr_sub + self.expr_mul + self.expr_div + self.expr_rem + self.expr_exp + self.expr_pos + self.expr_neg + self.get_instant; if self.max_depth <= 0 { Err("types.gen_integer.max_depth must be at least 1".to_string()) } else if (sum - 1.0).abs() > f64::EPSILON { Err(format!("types.gen_integer probability sum is = {}", sum)) } else { Ok(()) } } } toml_struct!{ struct GenReal { expr_add: f64, expr_sub: f64, expr_mul: f64, expr_div: f64, expr_rem: f64, expr_exp: f64, expr_pos: f64, expr_neg: f64, gen_integer: f64, get_instant: f64, max_depth: u32, } } impl GenReal { fn verify(&self) -> Result<(), String> { let sum = self.expr_add + self.expr_sub + self.expr_mul + self.expr_div + self.expr_rem + self.expr_exp + self.expr_pos + self.expr_neg + self.gen_integer + self.get_instant; if self.max_depth <= 0 { Err("types.gen_real.max_depth must be at least 1".to_string()) } else if (sum - 1.0).abs() > f64::EPSILON { Err(format!("types.gen_real probability sum is = {}", sum)) } else { Ok(()) } } } toml_struct!{ struct Dev { float_gen_distro_pos_stddiv: f32, float_gen_distro_neg_stddiv: f32, int_gen_distro_pos_stddiv: f32, int_gen_distro_neg_stddiv: f32, } } impl Dev { fn verify(&self) -> Result<(), String> { Ok(()) } }