aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-11-02 19:06:23 -0700
committerbnewbold <bnewbold@robocracy.org>2016-11-02 19:06:23 -0700
commitece67d35847ec89cbf4d3d13236ce5bb1d51b716 (patch)
tree9bb1e7eedb1792a652648d0319bb417935b267a4
parenta0ade9fdd10ed246bc228f74662ef2264d67f4e3 (diff)
downloadmodelthing-ece67d35847ec89cbf4d3d13236ce5bb1d51b716.tar.gz
modelthing-ece67d35847ec89cbf4d3d13236ce5bb1d51b716.zip
skeletal scheme transpilation
-rw-r--r--src/bin/mt-tool.rs9
-rw-r--r--src/lib.rs1
-rw-r--r--src/modelica_ast.rs38
-rw-r--r--src/transpile_scheme.rs55
4 files changed, 103 insertions, 0 deletions
diff --git a/src/bin/mt-tool.rs b/src/bin/mt-tool.rs
index 4d66339..8aac6ca 100644
--- a/src/bin/mt-tool.rs
+++ b/src/bin/mt-tool.rs
@@ -4,6 +4,7 @@ extern crate rustc_serialize;
extern crate getopts;
use modelthing::modelica_parser;
+use modelthing::transpile_scheme::TranspileScheme;
use getopts::Options;
use std::env;
use std::io::Read;
@@ -81,6 +82,14 @@ fn main() {
let cmd = matches.free[0].clone();
match cmd.as_str() {
"parse" => { parse_modelica_files(matches.free[1..].iter().map(|x| x.to_string()).collect()); },
+ "transpile" => {
+ if matches.free.len() != 2 {
+ println!("Expected a single path to load");
+ exit(-1);
+ }
+ let me = modelthing::load_model_entry(Path::new(&matches.free[1])).unwrap();
+ println!("{}", me.ast.repr_scheme().unwrap());
+ },
"list" => {
// XXX: search path?
for m in modelthing::search_models(Path::new("examples")) {
diff --git a/src/lib.rs b/src/lib.rs
index 1f7ed27..e6b2f41 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,6 +6,7 @@ extern crate toml;
pub mod modelica_parser;
pub mod modelica_ast;
+pub mod transpile_scheme;
use std::path::Path;
use std::fs;
diff --git a/src/modelica_ast.rs b/src/modelica_ast.rs
index 68eafaf..9e25b1b 100644
--- a/src/modelica_ast.rs
+++ b/src/modelica_ast.rs
@@ -1,5 +1,6 @@
use std::fmt::{Debug, Formatter, Error};
+use std::collections::HashMap;
#[derive(PartialEq)]
pub struct ModelicaModel {
@@ -59,6 +60,43 @@ pub enum BinOperator {
Subtract,
}
+//// Helpers
+
+impl ModelicaModel {
+
+ pub fn get_constant_vars(&self) -> HashMap<String,Expr> {
+ 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<String> {
+ // 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 {
diff --git a/src/transpile_scheme.rs b/src/transpile_scheme.rs
new file mode 100644
index 0000000..ce66d10
--- /dev/null
+++ b/src/transpile_scheme.rs
@@ -0,0 +1,55 @@
+
+use modelica_ast::*;
+
+pub trait TranspileScheme {
+ fn repr_scheme(&self) -> Result<String, String>;
+}
+
+
+impl TranspileScheme for ModelicaModel {
+ fn repr_scheme(&self) -> Result<String, String> {
+ let mut constants = vec![];
+ for (c, e) in self.get_constant_vars() {
+ constants.push(format!("({} {})",
+ c, try!(e.repr_scheme())));
+ }
+ let mut binds = vec![];
+ let mut outputs = vec![];
+ for eq in self.equations.iter() {
+ if let Expr::Ident(ref symb) = eq.lhs {
+ binds.push(format!("({} {})",
+ symb,
+ try!(eq.rhs.repr_scheme())));
+ outputs.push(symb.to_string());
+ } else {
+ return Err("Expected an identifier on LHS (in this partial implementation)".to_string())
+ }
+ }
+ Ok(format!(r#"(lambda ({args})
+ (let ({constants})
+ (letrec ({binds})
+ (list {outputs}))))"#,
+ args = self.get_free_vars().join(" "),
+ constants = constants.join("\n "),
+ binds = binds.join("\n "),
+ outputs = outputs.join(" ")))
+ }
+}
+
+impl TranspileScheme for Expr {
+ fn repr_scheme(&self) -> Result<String, String> {
+ use modelica_ast::Expr::*;
+ match *self {
+ Integer(e) => Ok(format!("{}", e)),
+ Float(e) => Ok(format!("{}", e)),
+ Ident(ref e) => Ok(format!("{}", e)),
+ Der(ref e) => Ok(format!("(der {})", try!(e.repr_scheme()))),
+ Abs(ref e) => Ok(format!("(abs {})", try!(e.repr_scheme()))),
+ BinExpr(op, ref l, ref r) =>
+ Ok(format!("({:?} {} {})",
+ op,
+ try!(l.repr_scheme()),
+ try!(r.repr_scheme()))),
+ }
+ }
+}