From fefe370e0bdb3e80427a26a3eb2727b47e22ed03 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Mon, 16 Jan 2017 18:04:14 -0800 Subject: add 'ode' transpile variant for javascript --- src/bin/mt-webface.rs | 3 ++- src/transpile_js.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/bin/mt-webface.rs b/src/bin/mt-webface.rs index b26e4fe..59b0621 100644 --- a/src/bin/mt-webface.rs +++ b/src/bin/mt-webface.rs @@ -20,7 +20,7 @@ use pencil::{redirect, abort}; use pencil::method::{Get, Post}; use regex::Regex; use modelthing::transpile_scheme::TranspileScheme; -use modelthing::transpile_js::TranspileJS; +use modelthing::transpile_js::{TranspileJS, TranspileJSODE}; use modelthing::repr_latex::ReprLaTeX; /* @@ -112,6 +112,7 @@ fn model_repr(r: &mut Request) -> PencilResult { match format { "scheme" => Ok(Response::from(me.ast.transpile_scheme().unwrap())), "javascript" => Ok(Response::from(me.ast.transpile_js().unwrap())), + "javascript_ode" => Ok(Response::from(me.ast.transpile_js_ode().unwrap())), "latex" => Ok(Response::from(me.ast.repr_latex().unwrap())), _ => abort(403), } diff --git a/src/transpile_js.rs b/src/transpile_js.rs index 219364a..225aa99 100644 --- a/src/transpile_js.rs +++ b/src/transpile_js.rs @@ -8,6 +8,10 @@ pub trait TranspileJS { fn transpile_js(&self) -> Result; } +pub trait TranspileJSODE { + fn transpile_js_ode(&self) -> Result; +} + impl TranspileJS for ModelicaModel { fn transpile_js(&self) -> Result { @@ -28,17 +32,59 @@ impl TranspileJS for ModelicaModel { } } let args: Vec = self.get_free_vars().iter().map(|s| s.clone()).collect(); - Ok(format!(r#"function {slug}({args}) {{ + Ok(format!(r#"function ({args}) {{ {constants} {binds} return [{outputs}]; - }}"#, - slug = "f", + }};"#, args = args.join(", "), constants = constants.join("\n "), binds = binds.join("\n "), outputs = outputs.join(", "))) } + +} + +impl TranspileJSODE for ModelicaModel { + + fn transpile_js_ode(&self) -> Result { + // TODO: distinguish true constants from parameters? + let mut params: Vec = vec![]; + let mut constants = vec![]; + for (c, e) in self.get_constant_vars() { + if let Some(v) = e { + constants.push(format!("var {} = {};", c, try!(v.transpile_js()))); + } else { + params.push(c); + } + } + let mut exprs = vec![]; + for eq in self.equations.iter() { + if let Expr::Der(ref der_of) = eq.lhs { + if let &Expr::Ident(_) = der_of.as_ref() { + // Ok + } else { + bail!("Non-trivial derivatives not supported (aka, of non-variable expressions)"); + } + exprs.push(try!(eq.rhs.transpile_js())); + } else { + bail!("Not a simple set of ODEs (aka, all derivatives on LHS of equations)"); + } + } + let args: Vec = self.get_free_vars().iter().map(|s| s.clone()).collect(); + Ok(format!(r#"function ({params}) {{ + return function({args}) {{ + {constants} + return [ + {expressions} + ]; + }}; + }};"#, + params = params.join(", "), + args = args.join(", "), + constants = constants.join("\n "), + expressions = exprs.join(",\n "))) + } } impl TranspileJS for Expr { @@ -51,8 +97,8 @@ impl TranspileJS for Expr { Boolean(false) => Ok(format!("false")), StringLiteral(ref s) => Ok(format!("\"{}\"", s)), Ident(ref e) => Ok(format!("{}", e)), - Der(ref e) => Ok(format!("der({})", try!(e.transpile_js()))), - Sign(ref e) => Ok(format!("sign({})", try!(e.transpile_js()))), + Der(_) => unimplemented!(), + Sign(_) => unimplemented!(), MathUnaryExpr(func, ref e) => Ok(format!("{:?}({})", func, try!(e.transpile_js()))), BinExpr(op, ref l, ref r) => { Ok(format!("({} {:?} {})", try!(l.transpile_js()), op, try!(r.transpile_js()))) -- cgit v1.2.3