mirror of
https://github.com/tiffany352/rink-rs
synced 2024-11-10 13:44:15 +00:00
Add name to substances, dedup fields with Rc
This commit is contained in:
parent
d9eb86fcca
commit
57ee25643a
2 changed files with 22 additions and 10 deletions
|
@ -5,7 +5,7 @@
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use number::{Number, Dim, Num};
|
||||
use ast::{Expr, Def, Defs};
|
||||
use substance::{Substance, Property};
|
||||
use substance::{Substance, Property, Properties};
|
||||
use std::rc::Rc;
|
||||
use value::Value;
|
||||
use Context;
|
||||
|
@ -309,9 +309,12 @@ impl Context {
|
|||
}).collect::<Result<BTreeMap<_,_>, _>>();
|
||||
match res {
|
||||
Ok(res) => {
|
||||
self.substances.insert(name, Substance {
|
||||
self.substances.insert(name.clone(), Substance {
|
||||
amount: Number::one(),
|
||||
properties: res,
|
||||
properties: Rc::new(Properties {
|
||||
name: name,
|
||||
properties: res,
|
||||
}),
|
||||
});
|
||||
},
|
||||
Err(e) => println!("Substance {} is malformed: {}", name, e),
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::collections::BTreeMap;
|
|||
use reply::{PropertyReply, SubstanceReply};
|
||||
use std::ops::{Mul, Div};
|
||||
use std::iter::once;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Property {
|
||||
|
@ -19,10 +20,16 @@ pub struct Property {
|
|||
pub doc: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Properties {
|
||||
pub name: String,
|
||||
pub properties: BTreeMap<String, Property>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Substance {
|
||||
pub amount: Number,
|
||||
pub properties: BTreeMap<String, Property>,
|
||||
pub properties: Rc<Properties>,
|
||||
}
|
||||
|
||||
pub enum SubstanceGetError {
|
||||
|
@ -33,15 +40,16 @@ pub enum SubstanceGetError {
|
|||
impl Substance {
|
||||
pub fn get(&self, name: &str) -> Result<Number, SubstanceGetError> {
|
||||
if self.amount.1.len() == 0 {
|
||||
self.properties.get(name)
|
||||
self.properties.properties.get(name)
|
||||
.ok_or_else(|| SubstanceGetError::Generic(format!(
|
||||
"No such property {}", name)))
|
||||
"No such property {} of {}",
|
||||
name, self.properties.name)))
|
||||
.map(|prop| {
|
||||
(&(&self.amount * &prop.output).unwrap() / &prop.input)
|
||||
.expect("Non-zero property")
|
||||
})
|
||||
} else {
|
||||
for (_name, prop) in &self.properties {
|
||||
for (_name, prop) in &self.properties.properties {
|
||||
if name == prop.output_name {
|
||||
let input = try!(
|
||||
(&prop.input / &self.amount).ok_or_else(
|
||||
|
@ -73,14 +81,15 @@ impl Substance {
|
|||
}
|
||||
}
|
||||
Err(SubstanceGetError::Generic(format!(
|
||||
"No such property {}", name)))
|
||||
"No such property {} of {}",
|
||||
name, self.properties.name)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_reply(&self, context: &Context) -> Result<SubstanceReply, String> {
|
||||
if self.amount.1.len() == 0 {
|
||||
Ok(SubstanceReply {
|
||||
properties: try!(self.properties.iter().map(|(k, v)| {
|
||||
properties: try!(self.properties.properties.iter().map(|(k, v)| {
|
||||
let (input, output) = if v.input.1.len() == 0 {
|
||||
let res = (&v.output * &self.amount).unwrap();
|
||||
(None, try!((&res / &v.input)
|
||||
|
@ -150,7 +159,7 @@ impl Substance {
|
|||
Ok(SubstanceReply {
|
||||
properties: try!(
|
||||
once(Ok(Some(amount)))
|
||||
.chain(self.properties.iter().map(func))
|
||||
.chain(self.properties.properties.iter().map(func))
|
||||
.collect::<Result<Vec<Option<PropertyReply>>, String>>())
|
||||
.into_iter()
|
||||
.filter_map(|x| x)
|
||||
|
|
Loading…
Reference in a new issue