aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2017-01-16 18:04:14 -0800
committerbnewbold <bnewbold@robocracy.org>2017-01-16 18:04:14 -0800
commitfefe370e0bdb3e80427a26a3eb2727b47e22ed03 (patch)
treeba5413c2facd2b454ae80ff4cd5fa86faa2cfd71
parent4a5fdd64541f79321d171697930680039123938d (diff)
downloadmodelthing-fefe370e0bdb3e80427a26a3eb2727b47e22ed03.tar.gz
modelthing-fefe370e0bdb3e80427a26a3eb2727b47e22ed03.zip
add 'ode' transpile variant for javascript
-rw-r--r--src/bin/mt-webface.rs3
-rw-r--r--src/transpile_js.rs56
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<String>;
}
+pub trait TranspileJSODE {
+ fn transpile_js_ode(&self) -> Result<String>;
+}
+
impl TranspileJS for ModelicaModel {
fn transpile_js(&self) -> Result<String> {
@@ -28,17 +32,59 @@ impl TranspileJS for ModelicaModel {
}
}
let args: Vec<String> = 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<String> {
+ // TODO: distinguish true constants from parameters?
+ let mut params: Vec<String> = 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<String> = 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())))