use std::fmt::{Debug, Formatter, Error}; use std::collections::HashMap; #[derive(PartialEq)] pub struct ModelicaModel { pub name: String, pub components: Vec, pub equations: Vec, pub connections: Vec, pub extends: Vec, } #[derive(Copy, Clone, PartialEq)] pub enum ComponentPrefix { // incomplete: eg, can be parameter and input Flow, Stream, Input, Output, Discrete, Parameter, Constant, } #[derive(PartialEq)] pub struct Component { pub prefix: Option, pub specifier: String, pub name: String, pub value: Option, pub units: Option, pub description: Option, } #[derive(Clone, PartialEq)] pub struct Connection { pub a: String, pub b: String, } #[derive(PartialEq)] pub struct SimpleEquation { pub lhs: Expr, pub rhs: Expr, } #[derive(PartialEq)] pub enum Expr { Integer(i64), Float(f64), Ident(String), Der(Box), Abs(Box), BinExpr(BinOperator, Box, Box), } #[derive(Copy, Clone, PartialEq)] pub enum BinOperator { Multiply, Divide, Add, Subtract, } //// Helpers impl ModelicaModel { pub fn get_constant_vars(&self) -> HashMap { let mut binds = HashMap::new(); for c in &self.components { match c.prefix { Some(ComponentPrefix::Constant) => { binds.insert(c.name.clone(), Expr::Integer(123)); }, Some(ComponentPrefix::Parameter) => { binds.insert(c.name.clone(), Expr::Float(4.56)); }, _ => (), } } binds } pub fn get_free_vars(&self) -> Vec { // 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, }); // Remove LHS (bound) vars let mut outputs = vec![]; for eq in self.equations.iter() { // TODO: if let Expr::Ident(ref symb) = eq.lhs { outputs.push(symb.to_string()); } } let vars = vars.filter(|v| !outputs.contains(&v.name)); vars.map(|c| c.name.clone()).collect() } } //// Debug Implementations impl Debug for ModelicaModel { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { try!(write!(fmt, "model {}\n", self.name)); for e in self.extends.iter() { try!(write!(fmt, " extends {};\n", e)); } for v in self.components.iter() { try!(write!(fmt, " {:?};\n", v)); } try!(write!(fmt, "equation\n")); for c in self.connections.iter() { try!(write!(fmt, " {:?};\n", c)); } for e in self.equations.iter() { try!(write!(fmt, " {:?};\n", e)); } write!(fmt, "end {};\n", self.name) } } impl Debug for ComponentPrefix { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::ComponentPrefix::*; write!(fmt, "{}", match *self { Flow => "flow", Stream => "stream", Input => "input", Output => "output", Discrete => "discrete", Parameter => "parameter", Constant => "constant", }) } } impl Debug for Component { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { write!(fmt, "{}{} {}", match self.prefix { Some(p) => format!("{:?} ", p), None => "".to_string(), }, self.specifier, self.name, ) } } impl Debug for Connection { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { write!(fmt, "connect({}, {})", self.a, self.b) } } impl Debug for SimpleEquation { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { write!(fmt, "{:?} = {:?}", self.lhs, self.rhs) } } impl Debug for Expr { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::Expr::*; match *self { Integer(e) => write!(fmt, "{}", e), Float(e) => write!(fmt, "{}", e), Ident(ref e) => write!(fmt, "{}", e), Der(ref e) => write!(fmt, "der({:?})", e), Abs(ref e) => write!(fmt, "abs({:?})", e), BinExpr(op, ref l, ref r) => write!(fmt, "({:?} {:?} {:?})", l, op, r), } } } impl Debug for BinOperator { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::BinOperator::*; match *self { Multiply => write!(fmt, "*"), Divide => write!(fmt, "/"), Add => write!(fmt, "+"), Subtract => write!(fmt, "-"), } } }