diff --git a/interpreter/src/lang/mod.rs b/interpreter/src/lang/mod.rs index 05b1714..87175c6 100644 --- a/interpreter/src/lang/mod.rs +++ b/interpreter/src/lang/mod.rs @@ -16,6 +16,7 @@ mod sorter; //mod statement; mod type_primitives; pub(crate) mod utility; +mod vec_op; pub use dictionary::LanguageDictionary; pub(crate) use error::LanguageError; @@ -32,6 +33,7 @@ pub use single_op::SingleItem; pub use sorter::{SortStatement, SortStatementFactory, Sorter, SorterFactory}; //pub(crate) use statement::Statement; pub use type_primitives::TypePrimitive; +pub use vec_op::VecOp; pub mod vocabulary; diff --git a/interpreter/src/lang/vec_op.rs b/interpreter/src/lang/vec_op.rs new file mode 100644 index 0000000..053bdb9 --- /dev/null +++ b/interpreter/src/lang/vec_op.rs @@ -0,0 +1,146 @@ +use std::fmt::{Debug, Display, Error, Formatter}; +use std::iter::Iterator; + +use crate::lang::{IteratorItem, Op, RuntimeError}; +use crate::lang::{RuntimeOp, RuntimeMsg, PseudoOp}; +use crate::Context; +use crate::Item; + +type IteratorItemMsg = Result; + +#[derive(Debug)] +pub struct VecOp { + context: Option, + vec: Vec, + index: usize, +} + +impl VecOp { + pub fn new(items: Vec) -> Self { + Self { + context: None, + vec: items, + index: 0, + } + } +} + +impl Display for VecOp { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "*vec*[{}..{}]", self.index, self.vec.len()) + } +} + +impl std::clone::Clone for VecOp { + fn clone(&self) -> Self { + Self { + context: None, + vec: self.vec.clone(), + index: self.index, + } + } +} + +impl Iterator for VecOp { + type Item = IteratorItem; + + fn next(&mut self) -> Option { + if self.index == self.vec.len() { + None + } else { + let item = self.vec[self.index].clone(); + self.index += 1; + Some(item) + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.vec.len(); + (len, Some(len)) + } +} + +impl Iterator for VecOp { + type Item = IteratorItem; + + fn next(&mut self) -> Option { + if self.index == self.vec.len() { + None + } else { + let item = self.vec[self.index].clone(); + self.index += 1; + Some(item.map_err(|e| e.with(RuntimeOp(PseudoOp::from_printable(self))))) + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.vec.len(); + (len, Some(len)) + } +} + +impl Op for VecOp { + fn enter(&mut self, ctx: Context) { + self.context = Some(ctx) + } + + fn escape(&mut self) -> Context { + self.context.take().unwrap() + } + + fn is_resetable(&self) -> bool { + true + } + + fn reset(&mut self) -> Result<(), RuntimeError> { + self.index = 0; + Ok(()) + } + + fn dup(&self) -> Box { + Box::new(Self { + context: None, + vec: self.vec.clone(), + index: 0, + }) + } +} + +impl Op for VecOp { + fn enter(&mut self, ctx: Context) { + self.context = Some(ctx) + } + + fn escape(&mut self) -> Context { + self.context.take().unwrap() + } + + fn is_resetable(&self) -> bool { + true + } + + fn reset(&mut self) -> Result<(), RuntimeError> { + self.index = 0; + Ok(()) + } + + fn dup(&self) -> Box { + Box::new(Self { + context: None, + vec: self.vec.clone(), + index: 0, + }) + } +} + +impl std::convert::From> for VecOp { + fn from(other: Vec) -> Self { + VecOp::new(other) + } +} + +impl std::convert::From> for VecOp { + fn from(other: Vec) -> Self { + VecOp::new(other) + } +} diff --git a/interpreter/src/lang/vocabulary/sql_query.rs b/interpreter/src/lang/vocabulary/sql_query.rs index fea7ae0..886a6a0 100644 --- a/interpreter/src/lang/vocabulary/sql_query.rs +++ b/interpreter/src/lang/vocabulary/sql_query.rs @@ -6,56 +6,48 @@ use crate::lang::utility::assert_token; use crate::lang::{ FunctionFactory, FunctionStatementFactory, IteratorItem, LanguageDictionary, Op, PseudoOp, }; -use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError}; +use crate::lang::{RuntimeError, RuntimeOp, SyntaxError}; use crate::tokens::Token; use crate::Context; -use crate::Item; //use super::db::*; #[derive(Debug)] pub struct SqlStatement { query: String, context: Option, - rows: Option>>, - current: usize, + rows: Option>, + is_complete: bool, } impl SqlStatement { - fn get_item(&mut self, increment: bool) -> Option { - let fake = PseudoOp::from_printable(self); - if let Some(rows) = &self.rows { - if increment { - if self.current == rows.len() { - return None; - } - self.current += 1; - } - if self.current >= rows.len() { - None - } else { - //Some(rows[self.current].clone()) - match rows[self.current].clone() { - Ok(item) => Some(Ok(item)), - Err(e) => Some(Err(e.with(RuntimeOp(fake)))), - } - } - } else { - Some(Err(RuntimeError { - line: 0, - op: fake, - msg: "Context error: rows is None".to_string(), - })) + fn get_item(&mut self) -> Option { + let result = self.rows.as_mut().unwrap().next().map(|opt| opt.map_err(|mut e| { + e.op = PseudoOp::from_printable(self); + e + })); + if result.is_none() { + self.is_complete = true; } + result } } impl Op for SqlStatement { fn enter(&mut self, ctx: Context) { - self.context = Some(ctx) + if let Some(rows) = &mut self.rows { + rows.enter(ctx); + } else { + self.context = Some(ctx); + } } fn escape(&mut self) -> Context { - self.context.take().unwrap() + if self.context.is_some() { + self.context.take().unwrap() + } else { + self.rows.as_mut().unwrap().escape() + } + } fn is_resetable(&self) -> bool { @@ -63,8 +55,10 @@ impl Op for SqlStatement { } fn reset(&mut self) -> Result<(), RuntimeError> { - self.rows = None; - self.current = 0; + if let Some(mut rows) = self.rows.take() { + self.context = Some(rows.escape()); + } + self.is_complete = false; Ok(()) } @@ -73,7 +67,7 @@ impl Op for SqlStatement { query: self.query.clone(), context: None, rows: None, - current: 0, + is_complete: false, }) } } @@ -84,7 +78,7 @@ impl std::clone::Clone for SqlStatement { query: self.query.clone(), context: None, // unecessary to include in clone (not used for displaying) rows: None, // unecessary to include - current: self.current, + is_complete: self.is_complete, } } } @@ -93,29 +87,31 @@ impl Iterator for SqlStatement { type Item = IteratorItem; fn next(&mut self) -> Option { + if self.is_complete { + return None; + } if self.rows.is_some() { // query has executed, return another result - self.get_item(true) + self.get_item() } else { - let fake = PseudoOp::from_printable(self); let ctx = self.context.as_mut().unwrap(); // query has not been executed yet match ctx.database.raw(&self.query) { Err(e) => { - self.rows = Some(Vec::with_capacity(0)); - Some(Err(e.with(RuntimeOp(fake)))) + self.is_complete = true; + Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))) } - Ok(rows) => { + Ok(mut rows) => { + rows.enter(self.context.take().unwrap()); self.rows = Some(rows); - self.get_item(false) + self.get_item() } } } } fn size_hint(&self) -> (usize, Option) { - let len = self.rows.as_ref().map(|x| x.len()); - (len.unwrap_or(0), len) + self.rows.as_ref().map(|x| x.size_hint()).unwrap_or_default() } } @@ -150,8 +146,8 @@ impl FunctionFactory for SqlFunctionFactory { Ok(SqlStatement { query: literal, context: None, - current: 0, rows: None, + is_complete: false, }) } } diff --git a/interpreter/src/lang/vocabulary/sql_simple_query.rs b/interpreter/src/lang/vocabulary/sql_simple_query.rs index 8a8f387..ae597bd 100644 --- a/interpreter/src/lang/vocabulary/sql_simple_query.rs +++ b/interpreter/src/lang/vocabulary/sql_simple_query.rs @@ -6,10 +6,9 @@ use crate::lang::utility::assert_token; use crate::lang::{ FunctionFactory, FunctionStatementFactory, IteratorItem, LanguageDictionary, Op, PseudoOp, }; -use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError}; +use crate::lang::{RuntimeError, RuntimeOp, SyntaxError}; use crate::tokens::Token; use crate::Context; -use crate::Item; #[derive(Debug, Clone)] enum QueryMode { @@ -65,46 +64,39 @@ pub struct SimpleSqlStatement { query: String, mode: QueryMode, context: Option, - rows: Option>>, - current: usize, + rows: Option>, + is_complete: bool, } impl SimpleSqlStatement { - fn get_item(&mut self, increment: bool) -> Option { - let fake = PseudoOp::from_printable(self); - if let Some(rows) = &self.rows { - if increment { - if self.current == rows.len() { - return None; - } - self.current += 1; - } - if self.current >= rows.len() { - None - } else { - //Some(rows[self.current].clone()) - match rows[self.current].clone() { - Ok(item) => Some(Ok(item)), - Err(e) => Some(Err(e.with(RuntimeOp(fake)))), - } - } - } else { - Some(Err(RuntimeError { - line: 0, - op: fake, - msg: "Context error: rows is None".to_string(), - })) + fn get_item(&mut self) -> Option { + let result = self.rows.as_mut().unwrap().next().map(|opt| opt.map_err(|mut e| { + e.op = PseudoOp::from_printable(self); + e + })); + if result.is_none() { + self.is_complete = true; } + result } } impl Op for SimpleSqlStatement { fn enter(&mut self, ctx: Context) { - self.context = Some(ctx) + if let Some(rows) = &mut self.rows { + rows.enter(ctx); + } else { + self.context = Some(ctx); + } } fn escape(&mut self) -> Context { - self.context.take().unwrap() + if self.context.is_some() { + self.context.take().unwrap() + } else { + self.rows.as_mut().unwrap().escape() + } + } fn is_resetable(&self) -> bool { @@ -112,8 +104,10 @@ impl Op for SimpleSqlStatement { } fn reset(&mut self) -> Result<(), RuntimeError> { - self.rows = None; - self.current = 0; + if let Some(mut rows) = self.rows.take() { + self.context = Some(rows.escape()); + } + self.is_complete = false; Ok(()) } @@ -123,7 +117,7 @@ impl Op for SimpleSqlStatement { mode: self.mode.clone(), context: None, rows: None, - current: 0, + is_complete: false, }) } } @@ -135,7 +129,7 @@ impl std::clone::Clone for SimpleSqlStatement { mode: self.mode.clone(), context: None, // unecessary to include in clone (not used for displaying) rows: None, // unecessary to include - current: self.current, + is_complete: self.is_complete, } } } @@ -144,11 +138,13 @@ impl Iterator for SimpleSqlStatement { type Item = IteratorItem; fn next(&mut self) -> Option { + if self.is_complete { + return None; + } if self.rows.is_some() { // query has executed, return another result - self.get_item(true) + self.get_item() } else { - let fake = PseudoOp::from_printable(self); let ctx = self.context.as_mut().unwrap(); // query has not been executed yet let query_result = match self.mode { @@ -159,20 +155,21 @@ impl Iterator for SimpleSqlStatement { }; match query_result { Err(e) => { - self.rows = Some(Vec::with_capacity(0)); - Some(Err(e.with(RuntimeOp(fake)))) + self.is_complete = true; + Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))) } - Ok(rows) => { + Ok(mut rows) => { + //drop(ctx); + rows.enter(self.context.take().unwrap()); self.rows = Some(rows); - self.get_item(false) + self.get_item() } } } } fn size_hint(&self) -> (usize, Option) { - let len = self.rows.as_ref().map(|x| x.len()); - (len.unwrap_or(0), len) + self.rows.as_ref().map(|x| x.size_hint()).unwrap_or_default() } } @@ -208,7 +205,7 @@ impl FunctionFactory for SimpleSqlFunctionFactory { query: literal, mode: QueryMode::from_name(mode_name)?, context: None, - current: 0, + is_complete: false, rows: None, }) } diff --git a/interpreter/src/processing/sql.rs b/interpreter/src/processing/sql.rs index 4c71d58..8fc3094 100644 --- a/interpreter/src/processing/sql.rs +++ b/interpreter/src/processing/sql.rs @@ -4,9 +4,10 @@ use std::fmt::Write; use crate::lang::db::*; use crate::lang::RuntimeMsg; +use crate::lang::{Op, VecOp}; use crate::Item; -pub type QueryResult = Result>, RuntimeMsg>; +pub type QueryResult = Result, RuntimeMsg>; /// SQL querying functionality, loosely de-coupled from any specific SQL dialect (excluding raw call) pub trait DatabaseQuerier: Debug { @@ -56,10 +57,10 @@ impl SQLiteExecutor { self.gen_db_maybe()?; let conn = self.sqlite_connection.as_mut().unwrap(); match perform_single_param_query(conn, query, param) { - Ok(items) => Ok(items + Ok(items) => Ok(Box::new(VecOp::from(items .into_iter() .map(|item| item.map_err(|e| RuntimeMsg(format!("SQL item mapping error: {}", e)))) - .collect()), + .collect::>()))), Err(e) => Err(RuntimeMsg(e)), } } @@ -71,10 +72,10 @@ impl DatabaseQuerier for SQLiteExecutor { let conn = self.sqlite_connection.as_mut().unwrap(); // execute query match perform_query(conn, query) { - Ok(items) => Ok(items + Ok(items) => Ok(Box::new(VecOp::from(items .into_iter() .map(|item| item.map_err(|e| RuntimeMsg(format!("SQL item mapping error: {}", e)))) - .collect()), + .collect::>()))), Err(e) => Err(RuntimeMsg(e)), } } @@ -299,3 +300,32 @@ fn rows_to_item( .set_field_chain("year", meta.date.into()); item } + +#[derive(Default, Debug)] +pub struct SQLiteTranspileExecutor; + +impl DatabaseQuerier for SQLiteTranspileExecutor { + fn raw(&mut self, query: &str) -> QueryResult { + Err(RuntimeMsg("Unimplemented".to_owned())) + } + + fn artist_like(&mut self, query: &str) -> QueryResult { + Err(RuntimeMsg("Unimplemented".to_owned())) + } + + fn album_like(&mut self, query: &str) -> QueryResult { + Err(RuntimeMsg("Unimplemented".to_owned())) + } + + fn song_like(&mut self, query: &str) -> QueryResult { + Err(RuntimeMsg("Unimplemented".to_owned())) + } + + fn genre_like(&mut self, query: &str) -> QueryResult { + Err(RuntimeMsg("Unimplemented".to_owned())) + } + + fn init_with_params(&mut self, _params: &HashMap) -> Result<(), RuntimeMsg> { + Ok(()) + } +}