From 72d03e21dd479b161536d3b2e8dc63f2809f1278 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Thu, 8 Jun 2017 22:15:48 -0500 Subject: [PATCH] Add the build module. Builder struct that takes a list of Statements and constructs a Tuple from it. --- src/build.rs | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/parse.rs | 4 +- 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 src/build.rs diff --git a/src/build.rs b/src/build.rs new file mode 100644 index 0000000..df67d3d --- /dev/null +++ b/src/build.rs @@ -0,0 +1,167 @@ +use parse::{parse, Statement, Expression, Value, FieldList}; + +use std::error::Error; +use std::collections::HashMap; +use std::convert::From; + +quick_error! { + #[derive(Debug,PartialEq)] + pub enum BuildError { + TypeFail(msg: String) { + description("Eval Error") + display("Eval Error {}", msg) + } + NoSuchSymbol(msg: String) { + description("Eval Error") + display("Eval Error {}", msg) + } + TODO(msg: String) { + description("Eval Error") + display("Eval Error {}", msg) + } + } +} + +/// BuildResult is the result of a build. +type BuildResult = Result<(), Box>; + +/// Val is the type of a value for a field in a Tuple. +#[derive(PartialEq,Debug)] +pub enum Val<'a> { + Int(i64), + Float(f64), + String(&'a str), + Symbol(&'a str), + Tuple(FieldList<'a>), +} + +impl<'a> From> for Val<'a> { + fn from(v: Value<'a>) -> Self { + match v { + Value::Int(i) => Val::Int(i), + Value::Float(f) => Val::Float(f), + Value::String(s) => Val::String(s), + Value::Symbol(s) => Val::Symbol(s), + Value::Tuple(ref fields) => { + Val::Tuple(Vec::new()) + } + } + } +} + +/// Tuple defines a set of fields. +#[derive(PartialEq,Debug)] +pub struct Tuple<'a>(HashMap<&'a str, Val<'a>>); + +/// Builder parses one or more statements into a out Tuple. +pub struct Builder<'a> { + /// env is the set of key value pairs provided at build time. + env: HashMap<&'a str, &'a str>, + /// assets are other parsed files from import statements. They + /// are keyed by the normalized import path. This acts as a cache + /// so multiple imports of the same file don't have to be parsed + /// multiple times. + assets: HashMap<&'a str, Tuple<'a>>, + /// out is our built output. + out: Tuple<'a>, +} + +impl<'a> Builder<'a> { + /// new_builder constructs Builder with initialized fields ready to parse. + pub fn new_builder() -> Self { + Builder { + env: HashMap::new(), + assets: HashMap::new(), + out: Tuple(HashMap::new()), + } + } + + pub fn build_dir(&self, name: &str) -> BuildResult { + Ok(()) + } + + pub fn build_file(&self, name: &str) -> BuildResult { + Ok(()) + } + + pub fn build(&self, ast: Vec) -> BuildResult { + // TODO(jwall): + for stmt in ast.iter() { + self.build_stmt(stmt); + } + Ok(()) + } + + fn eval_expr(&'a self, expr: Expression<'a>) -> Result> { + match expr { + Expression::Simple(val) => { + Ok(Val::from(val)) + }, + Expression::Add(v, expr) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Sub(v, expr) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Mul(v, expr) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Div(v, expr) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Copy(sel, fields) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Selector(sel) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Grouped(expr) => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Call{lambda: sel, arglist: args} => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Lambda{arglist: args, tuple: fields} => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + Expression::Select{val: target, default: def_expr, tuple: fields} => { + Err(Box::new( + BuildError::TODO( + "TODO(jwall): Unimplemented Expression".to_string()))) + }, + } + } + + fn build_stmt(&self, stmt: &Statement) -> BuildResult { + match stmt { + &Statement::Let { name: ref sym, value: ref expr } => { + // TODO + } + &Statement::Import { path: ref val, name: ref sym } => { + // TODO + } + &Statement::Expression(ref expr) => { + // TODO + } + }; + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index b14a474..c25d98a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,9 +5,11 @@ extern crate nom; extern crate quick_error; pub mod parse; +pub mod build; pub use parse::Value; pub use parse::Expression; pub use parse::Statement; pub use parse::parse; +pub use build::Builder; diff --git a/src/parse.rs b/src/parse.rs index 60085f2..58437c5 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -17,8 +17,8 @@ use nom::{alpha, is_alphanumeric, digit, IResult}; type ParseResult = Result>; -type FieldList<'a> = Vec<(&'a str, Expression<'a>)>; // str is expected to be a symbol -type SelectorList<'a> = Vec<&'a str>; // str is expected to always be a symbol. +pub type FieldList<'a> = Vec<(&'a str, Expression<'a>)>; // str is expected to be a symbol +pub type SelectorList<'a> = Vec<&'a str>; // str is expected to always be a symbol. /// Value represents a Value in the UCG parsed AST. #[derive(Debug,PartialEq)]