diff options
author | bnewbold <bnewbold@robocracy.org> | 2016-12-25 22:16:46 -0800 |
---|---|---|
committer | bnewbold <bnewbold@robocracy.org> | 2016-12-25 22:17:22 -0800 |
commit | 14d055dcc41044061357f206fe4ed71ce61fffce (patch) | |
tree | 40ba0c183d938e8ef9309e710f003f298350d27f | |
parent | 68aa8cb130ff68395c416b36a1e5661e6fa18e5d (diff) | |
download | modelthing-14d055dcc41044061357f206fe4ed71ce61fffce.tar.gz modelthing-14d055dcc41044061357f206fe4ed71ce61fffce.zip |
rustfmt
-rw-r--r-- | src/lib.rs | 35 | ||||
-rw-r--r-- | src/modelica_model.rs | 178 | ||||
-rw-r--r-- | src/transpile_js.rs | 31 | ||||
-rw-r--r-- | src/transpile_scheme.rs | 27 |
4 files changed, 163 insertions, 108 deletions
@@ -47,14 +47,16 @@ pub struct ModelEntry { pub markdown: String, } -pub fn parse_metadata(raw: String) -> Result<ModelMetadata,String> { +pub fn parse_metadata(raw: String) -> Result<ModelMetadata, String> { let root = toml::Parser::new(&raw).parse().unwrap(); let model = root.get("model") .expect("missing 'model' section") - .as_table().unwrap(); + .as_table() + .unwrap(); let variables = root.get("variables") .expect("missing 'variables' section") - .as_table().unwrap(); + .as_table() + .unwrap(); let mut vars = vec![]; for (slug, info) in variables { let info = info.as_table().unwrap(); @@ -82,24 +84,30 @@ pub fn parse_metadata(raw: String) -> Result<ModelMetadata,String> { }) } -pub fn load_model_entry(p: &Path) -> Result<ModelEntry,String> { +pub fn load_model_entry(p: &Path) -> Result<ModelEntry, String> { debug!("Attempting to load model from: {:?}", p); let ast = { let mut s = String::new(); - try!(File::open(p.join("model.modelica")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string())); + try!(File::open(p.join("model.modelica")) + .and_then(|mut f| f.read_to_string(&mut s)) + .map_err(|e| e.to_string())); try!(modelica_parser::parser::parse_model(&s).map_err(|e| format!("{:?}", e))) }; let metadata = { let mut s = String::new(); - try!(File::open(p.join("metadata.toml")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string())); + try!(File::open(p.join("metadata.toml")) + .and_then(|mut f| f.read_to_string(&mut s)) + .map_err(|e| e.to_string())); parse_metadata(s).unwrap() }; let markdown = { let mut s = String::new(); - try!(File::open(p.join("page.md")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string())); + try!(File::open(p.join("page.md")) + .and_then(|mut f| f.read_to_string(&mut s)) + .map_err(|e| e.to_string())); s }; @@ -112,12 +120,13 @@ pub fn load_model_entry(p: &Path) -> Result<ModelEntry,String> { pub fn search_models(p: &Path) -> Vec<String> { if fs::metadata(p).unwrap().is_dir() { - fs::read_dir(p).unwrap() - .map(|x| x.unwrap()) - .filter(|x| x.metadata().unwrap().is_dir()) - .filter(|x| x.path().join("model.modelica").exists()) - .map(|x| x.path().to_string_lossy().to_string()) - .collect() + fs::read_dir(p) + .unwrap() + .map(|x| x.unwrap()) + .filter(|x| x.metadata().unwrap().is_dir()) + .filter(|x| x.path().join("model.modelica").exists()) + .map(|x| x.path().to_string_lossy().to_string()) + .collect() } else { vec![] } diff --git a/src/modelica_model.rs b/src/modelica_model.rs index 36c5a2e..81680d6 100644 --- a/src/modelica_model.rs +++ b/src/modelica_model.rs @@ -8,23 +8,29 @@ use std::collections::HashSet; use self::modelica_parser::ast::*; -//// Helpers +/// / Helpers pub trait ModelicaModelExt { - fn get_constant_vars(&self) -> HashMap<String,Option<Expr>>; + fn get_constant_vars(&self) -> HashMap<String, Option<Expr>>; fn get_free_vars(&self) -> Vec<String>; - fn solve_for(&self, indep_vars: Vec<String>, dep_vars: Vec<String>) -> Result<ModelicaModel,String>; + fn solve_for(&self, + indep_vars: Vec<String>, + dep_vars: Vec<String>) + -> Result<ModelicaModel, String>; } impl ModelicaModelExt for ModelicaModel { - - fn get_constant_vars(&self) -> HashMap<String,Option<Expr>> { + fn get_constant_vars(&self) -> HashMap<String, Option<Expr>> { let mut binds = HashMap::new(); // XXX: actually implement this... for c in &self.components { match c.prefix { - Some(ComponentPrefix::Constant) => { binds.insert(c.name.clone(), Some(Expr::Integer(123))); }, - Some(ComponentPrefix::Parameter) => { binds.insert(c.name.clone(), Some(Expr::Float(4.56))); }, + Some(ComponentPrefix::Constant) => { + binds.insert(c.name.clone(), Some(Expr::Integer(123))); + } + Some(ComponentPrefix::Parameter) => { + binds.insert(c.name.clone(), Some(Expr::Float(4.56))); + } _ => (), } } @@ -38,9 +44,10 @@ impl ModelicaModelExt for ModelicaModel { fn get_free_vars(&self) -> Vec<String> { // Start with components, and remove constants and parameters let vars = self.components.iter().filter(|v| match v.prefix { - Some(ComponentPrefix::Constant) | Some(ComponentPrefix::Parameter) => false, - _ => true, - }); + Some(ComponentPrefix::Constant) | + Some(ComponentPrefix::Parameter) => false, + _ => true, + }); // Remove LHS (bound) vars let mut outputs = vec![]; @@ -63,7 +70,10 @@ impl ModelicaModelExt for ModelicaModel { // N equations with unknowns // // TODO: allow passing in Q - fn solve_for(&self, indep_vars: Vec<String>, dep_vars: Vec<String>) -> Result<ModelicaModel,String> { + fn solve_for(&self, + indep_vars: Vec<String>, + dep_vars: Vec<String>) + -> Result<ModelicaModel, String> { let constants = self.get_constant_vars(); let mut all_vars: HashSet<String> = HashSet::new(); for eqn in &self.equations { @@ -82,25 +92,30 @@ impl ModelicaModelExt for ModelicaModel { // check that V = Q + P + M if all_vars.len() != (constants.len() + indep_vars.len() + dep_vars.len()) { return Err(format!("Variable counts don't add up (V={} Q={} P={} M={})", - all_vars.len(), - constants.len(), - indep_vars.len(), - dep_vars.len())); + all_vars.len(), + constants.len(), + indep_vars.len(), + dep_vars.len())); } // check that all constants are bound and simple for (name, value) in &constants { match *value { None => return Err(format!("UnderSpecifiedConstant: {}", name)), - Some(Expr::Integer(_)) | Some(Expr::Float(_)) => (), // Ok, - Some(_) => return Err(format!("NaiveImplementation: can't handle constant: {}", name)), + Some(Expr::Integer(_)) | + Some(Expr::Float(_)) => (), // Ok, + Some(_) => { + return Err(format!("NaiveImplementation: can't handle constant: {}", name)) + } } } // check that there is a depdendent variable in each equation for eqn in &self.equations { if intersect_strings(&dep_vars, &eqn.identifiers()).len() == 0 { - return Err("NaiveImplementation/OverConstrained: at least one equation is missing a dependent variable".to_string()); + return Err("NaiveImplementation/OverConstrained: at least one equation is \ + missing a dependent variable" + .to_string()); } } @@ -110,17 +125,21 @@ impl ModelicaModelExt for ModelicaModel { } println!("Soliving for {:?} in terms of params {:?} and constants {:?}, with {} equations", - dep_vars, indep_vars, constants, self.equations.len()); + dep_vars, + indep_vars, + constants, + self.equations.len()); let mut unsolved_eqns = self.equations.clone(); let mut solved: Vec<SimpleEquation> = vec![]; let mut unsolved_vars = dep_vars.clone(); while unsolved_eqns.len() > 0 { - let next_i = unsolved_eqns - .iter() + let next_i = unsolved_eqns.iter() .position(|ref x| intersect_strings(&unsolved_vars, &x.identifiers()).len() == 1); let eqn = match next_i { - None => { return Err("NaiveImplementation (or poor equation selection?)".to_string()); }, + None => { + return Err("NaiveImplementation (or poor equation selection?)".to_string()); + } Some(i) => unsolved_eqns.remove(i), }; let ref var = intersect_strings(&unsolved_vars, &eqn.identifiers())[0]; @@ -128,10 +147,10 @@ impl ModelicaModelExt for ModelicaModel { solved.push(eqn); let var_i = unsolved_vars.iter().position(|ref x| x == &var).unwrap(); unsolved_vars.remove(var_i); - }; + } // TODO: sort output equations by LHS - Ok(ModelicaModel{ + Ok(ModelicaModel { name: self.name.clone(), description: self.description.clone(), components: self.components.clone(), @@ -152,13 +171,12 @@ fn intersect_strings(a: &Vec<String>, b: &Vec<String>) -> Vec<String> { } pub trait SimpleEquationExt { - fn rebalance_for(&self, ident: String) -> Result<SimpleEquation,String>; - fn simplify_lhs(&self, ident: &str) -> Result<SimpleEquation,String>; + fn rebalance_for(&self, ident: String) -> Result<SimpleEquation, String>; + fn simplify_lhs(&self, ident: &str) -> Result<SimpleEquation, String>; } impl SimpleEquationExt for SimpleEquation { - - fn rebalance_for(&self, ident: String) -> Result<SimpleEquation,String> { + fn rebalance_for(&self, ident: String) -> Result<SimpleEquation, String> { let lvars = self.lhs.identifiers(); let rvars = self.rhs.identifiers(); @@ -166,9 +184,13 @@ impl SimpleEquationExt for SimpleEquation { (true, true) => Err("SymbolicError: NaiveImplementation".to_string()), (false, false) => Err("SymbolicError: VariableNotFound".to_string()), (true, false) => self.simplify_lhs(&ident), - (false, true) => - SimpleEquation{lhs: self.rhs.clone(), - rhs: self.lhs.clone()}.simplify_lhs(&ident), + (false, true) => { + SimpleEquation { + lhs: self.rhs.clone(), + rhs: self.lhs.clone(), + } + .simplify_lhs(&ident) + } }; match ret { Ok(eqn) => { @@ -176,56 +198,86 @@ impl SimpleEquationExt for SimpleEquation { Err("SymbolicError: NaiveImplementation".to_string()) } else { Ok(eqn) - }}, + } + } Err(_) => ret, } } - fn simplify_lhs(&self, ident: &str) -> Result<SimpleEquation,String> { + fn simplify_lhs(&self, ident: &str) -> Result<SimpleEquation, String> { use modelica_parser::ast::Expr::*; use modelica_parser::ast::BinOperator::*; match self.lhs { Ident(ref s) if s == ident => Ok((*self).clone()), - Ident(_) | Integer(_) | Float(_) | Boolean(_) | StringLiteral(_) => - Err("SymbolicError: InternalError: expected var on LHS".to_string()), - Der(_) | MathUnaryExpr(_,_) | Sign(_) | Array(_) => - Err("SymbolicError: NaiveImplementation: can't simplify".to_string()), + Ident(_) | Integer(_) | Float(_) | Boolean(_) | StringLiteral(_) => { + Err("SymbolicError: InternalError: expected var on LHS".to_string()) + } + Der(_) | + MathUnaryExpr(_, _) | + Sign(_) | + Array(_) => Err("SymbolicError: NaiveImplementation: can't simplify".to_string()), // TODO: create a macro for the below... BinExpr(Multiply, ref a, ref b) if a.contains(ident) => { - SimpleEquation{ - lhs: *a.clone(), - rhs: BinExpr(Divide, Box::new(self.rhs.clone()), b.clone())}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *a.clone(), + rhs: BinExpr(Divide, Box::new(self.rhs.clone()), b.clone()), + } + .simplify_lhs(&ident) + } BinExpr(Multiply, ref a, ref b) if b.contains(ident) => { - SimpleEquation{ - lhs: *b.clone(), - rhs: BinExpr(Divide, Box::new(self.rhs.clone()), a.clone())}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *b.clone(), + rhs: BinExpr(Divide, Box::new(self.rhs.clone()), a.clone()), + } + .simplify_lhs(&ident) + } BinExpr(Divide, ref a, ref b) if a.contains(ident) => { - SimpleEquation{ - lhs: *a.clone(), - rhs: BinExpr(Multiply, Box::new(self.rhs.clone()), b.clone())}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *a.clone(), + rhs: BinExpr(Multiply, Box::new(self.rhs.clone()), b.clone()), + } + .simplify_lhs(&ident) + } BinExpr(Divide, ref a, ref b) if b.contains(ident) => { - SimpleEquation{ - lhs: *b.clone(), - rhs: BinExpr(Divide, a.clone(), Box::new(self.rhs.clone()))}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *b.clone(), + rhs: BinExpr(Divide, a.clone(), Box::new(self.rhs.clone())), + } + .simplify_lhs(&ident) + } BinExpr(Add, ref a, ref b) if a.contains(ident) => { - SimpleEquation{ - lhs: *a.clone(), - rhs: BinExpr(Subtract, Box::new(self.rhs.clone()), b.clone())}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *a.clone(), + rhs: BinExpr(Subtract, Box::new(self.rhs.clone()), b.clone()), + } + .simplify_lhs(&ident) + } BinExpr(Add, ref a, ref b) if b.contains(ident) => { - SimpleEquation{ - lhs: *b.clone(), - rhs: BinExpr(Subtract, Box::new(self.rhs.clone()), a.clone())}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *b.clone(), + rhs: BinExpr(Subtract, Box::new(self.rhs.clone()), a.clone()), + } + .simplify_lhs(&ident) + } BinExpr(Subtract, ref a, ref b) if a.contains(ident) => { - SimpleEquation{ - lhs: *a.clone(), - rhs: BinExpr(Add, Box::new(self.rhs.clone()), b.clone())}.simplify_lhs(&ident) }, + SimpleEquation { + lhs: *a.clone(), + rhs: BinExpr(Add, Box::new(self.rhs.clone()), b.clone()), + } + .simplify_lhs(&ident) + } BinExpr(Subtract, ref a, ref b) if b.contains(ident) => { - SimpleEquation{ - lhs: *b.clone(), - rhs: BinExpr(Subtract, a.clone(), Box::new(self.rhs.clone()))}.simplify_lhs(&ident) }, - BinExpr(_, _, _) => Err("SymbolicError: NotImplemented BinOperator (or else couldn't find var...)".to_string()), + SimpleEquation { + lhs: *b.clone(), + rhs: BinExpr(Subtract, a.clone(), Box::new(self.rhs.clone())), + } + .simplify_lhs(&ident) + } + BinExpr(_, _, _) => { + Err("SymbolicError: NotImplemented BinOperator (or else couldn't find var...)" + .to_string()) + } // in case we add opers: _ => Err("NotImplemented".to_string()), } } } - diff --git a/src/transpile_js.rs b/src/transpile_js.rs index d4ed5f7..1fa6075 100644 --- a/src/transpile_js.rs +++ b/src/transpile_js.rs @@ -13,33 +13,30 @@ impl TranspileJS for ModelicaModel { let mut constants = vec![]; for (c, e) in self.get_constant_vars() { if let Some(v) = e { - constants.push(format!("var {} = {};", - c, try!(v.repr_js()))); + constants.push(format!("var {} = {};", c, try!(v.repr_js()))); } } let mut binds = vec![]; let mut outputs = vec![]; for eq in self.equations.iter() { if let Expr::Ident(ref symb) = eq.lhs { - binds.push(format!("var {} = {};", - symb, - try!(eq.rhs.repr_js()))); + binds.push(format!("var {} = {};", symb, try!(eq.rhs.repr_js()))); outputs.push(symb.to_string()); } else { - return Err("Expected an identifier on LHS (in this partial implementation)".to_string()) + return Err("Expected an identifier on LHS (in this partial implementation)" + .to_string()); } } - Ok(format!( - r#"function {slug}({args}) {{ + Ok(format!(r#"function {slug}({args}) {{ {constants} {binds} return [{outputs}]; }}"#, - slug = "f", - args = self.get_free_vars().join(", "), - constants = constants.join("\n "), - binds = binds.join("\n "), - outputs = outputs.join(", "))) + slug = "f", + args = self.get_free_vars().join(", "), + constants = constants.join("\n "), + binds = binds.join("\n "), + outputs = outputs.join(", "))) } } @@ -56,11 +53,9 @@ impl TranspileJS for Expr { Der(ref e) => Ok(format!("der({})", try!(e.repr_js()))), Sign(ref e) => Ok(format!("sign({})", try!(e.repr_js()))), MathUnaryExpr(func, ref e) => Ok(format!("{:?}({})", func, try!(e.repr_js()))), - BinExpr(op, ref l, ref r) => - Ok(format!("({} {:?} {})", - try!(l.repr_js()), - op, - try!(r.repr_js()))), + BinExpr(op, ref l, ref r) => { + Ok(format!("({} {:?} {})", try!(l.repr_js()), op, try!(r.repr_js()))) + } Array(_) => Err("Array unimplemented".to_string()), } } diff --git a/src/transpile_scheme.rs b/src/transpile_scheme.rs index 79492d8..7c25047 100644 --- a/src/transpile_scheme.rs +++ b/src/transpile_scheme.rs @@ -13,30 +13,28 @@ impl TranspileScheme for ModelicaModel { let mut constants = vec![]; for (c, e) in self.get_constant_vars() { if let Some(v) = e { - constants.push(format!("({} {})", - c, try!(v.repr_scheme()))); + constants.push(format!("({} {})", c, try!(v.repr_scheme()))); } } let mut binds = vec![]; let mut outputs = vec![]; for eq in self.equations.iter() { if let Expr::Ident(ref symb) = eq.lhs { - binds.push(format!("({} {})", - symb, - try!(eq.rhs.repr_scheme()))); + binds.push(format!("({} {})", symb, try!(eq.rhs.repr_scheme()))); outputs.push(symb.to_string()); } else { - return Err("Expected an identifier on LHS (in this partial implementation)".to_string()) + return Err("Expected an identifier on LHS (in this partial implementation)" + .to_string()); } } Ok(format!(r#"(lambda ({args}) (let ({constants}) (letrec ({binds}) (list {outputs}))))"#, - args = self.get_free_vars().join(" "), - constants = constants.join("\n "), - binds = binds.join("\n "), - outputs = outputs.join(" "))) + args = self.get_free_vars().join(" "), + constants = constants.join("\n "), + binds = binds.join("\n "), + outputs = outputs.join(" "))) } } @@ -53,11 +51,12 @@ impl TranspileScheme for Expr { Der(ref e) => Ok(format!("(der {})", try!(e.repr_scheme()))), Sign(ref e) => Ok(format!("(sign {})", try!(e.repr_scheme()))), MathUnaryExpr(func, ref e) => Ok(format!("({:?} {})", func, try!(e.repr_scheme()))), - BinExpr(op, ref l, ref r) => + BinExpr(op, ref l, ref r) => { Ok(format!("({:?} {} {})", - op, - try!(l.repr_scheme()), - try!(r.repr_scheme()))), + op, + try!(l.repr_scheme()), + try!(r.repr_scheme()))) + } Array(_) => Err("Array unimplemented".to_string()), } } |