diff options
| author | bnewbold <bnewbold@robocracy.org> | 2016-12-25 23:33:20 -0800 | 
|---|---|---|
| committer | bnewbold <bnewbold@robocracy.org> | 2016-12-25 23:33:20 -0800 | 
| commit | 3e3f933595f64083e41433075e66aa275af66c6c (patch) | |
| tree | 4ebf1f47d98c3371cfeb3a89e5b473edd5262af3 /src | |
| parent | 14d055dcc41044061357f206fe4ed71ce61fffce (diff) | |
| download | modelthing-3e3f933595f64083e41433075e66aa275af66c6c.tar.gz modelthing-3e3f933595f64083e41433075e66aa275af66c6c.zip  | |
basic AST substituting (finishing first stab at solve_for)
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/mt-tool.rs | 6 | ||||
| -rw-r--r-- | src/modelica_model.rs | 31 | 
2 files changed, 33 insertions, 4 deletions
diff --git a/src/bin/mt-tool.rs b/src/bin/mt-tool.rs index 317ac20..37b1705 100644 --- a/src/bin/mt-tool.rs +++ b/src/bin/mt-tool.rs @@ -56,9 +56,9 @@ fn main() {              .arg_from_usage("<DIR> 'model to load'"))          .subcommand(SubCommand::with_name("solve_for")              .about("") -            .arg_from_usage("<DIR> 'model to load' -                             --dep <VAR>... 'dependent variable' -                             --indep <VAR>... 'independent variable'")) +            .arg_from_usage("<DIR> 'model to load'") +            .arg_from_usage("--dep <VAR>... 'dependent variable'") +            .arg_from_usage("--indep <VAR>... 'independent variable'"))          .get_matches(); diff --git a/src/modelica_model.rs b/src/modelica_model.rs index 81680d6..7b77123 100644 --- a/src/modelica_model.rs +++ b/src/modelica_model.rs @@ -134,6 +134,7 @@ impl ModelicaModelExt for ModelicaModel {          let mut solved: Vec<SimpleEquation> = vec![];          let mut unsolved_vars = dep_vars.clone();          while unsolved_eqns.len() > 0 { +            println!("vars: {:?}    eqns: {:?}", &unsolved_vars, &unsolved_eqns);              let next_i = unsolved_eqns.iter()                  .position(|ref x| intersect_strings(&unsolved_vars, &x.identifiers()).len() == 1);              let eqn = match next_i { @@ -143,13 +144,20 @@ impl ModelicaModelExt for ModelicaModel {                  Some(i) => unsolved_eqns.remove(i),              };              let ref var = intersect_strings(&unsolved_vars, &eqn.identifiers())[0]; +            println!("solving: {}; {:?}", var, eqn);              let eqn = eqn.rebalance_for(var.to_string()).expect("rebalance for success"); +            println!("got: {:?}", eqn); +            // Replace all other references to var with RHS of solved equation +            unsolved_eqns = unsolved_eqns.iter().map(|ref e| +                SimpleEquation{ +                    lhs: substitute_with(&e.lhs, &Expr::Ident(var.to_string()), &eqn.rhs), +                    rhs: substitute_with(&e.rhs, &Expr::Ident(var.to_string()), &eqn.rhs), +                }).collect();              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 {              name: self.name.clone(),              description: self.description.clone(), @@ -160,6 +168,27 @@ impl ModelicaModelExt for ModelicaModel {      }  } +// Recurses through 'original', replacing all instances of 'a' with 'b' +fn substitute_with(original: &Expr, a: &Expr, b: &Expr) -> Expr { +    use modelica_parser::ast::Expr::*; +    println!("original: {:?}  replacing: {:?}   with: {:?}", original, a, b); +    if *original == *a { +        return b.clone(); +    } +    match *original { +        Integer(_) | Float(_) | Boolean(_) | StringLiteral(_) | Ident(_) => original.clone(), +        Der(ref e) => Der(Box::new(substitute_with(e, a, b))), +        Sign(ref e) => Sign(Box::new(substitute_with(e, a, b))), +        MathUnaryExpr(muf, ref e) => +            MathUnaryExpr(muf, Box::new(substitute_with(e, a, b))), +        BinExpr(bo, ref e1, ref e2) => +            BinExpr(bo, +                    Box::new(substitute_with(e1, a, b)), +                    Box::new(substitute_with(e2, a, b))), +        Array(ref l) => Array(l.iter().map(|ref e| substitute_with(e, a, b)).collect()), +    } +} +  fn intersect_strings(a: &Vec<String>, b: &Vec<String>) -> Vec<String> {      let mut both = vec![];      for e in a {  | 
