diff --git a/TODO.md b/TODO.md index 9637952187..2879da2b71 100644 --- a/TODO.md +++ b/TODO.md @@ -12,10 +12,10 @@ - [x] subcommand alias - [x] type inference from successful parse (eg not `List` but `List`) - [x] parsing tables +- [ ] Column path - [ ] ...rest without calling it rest - [ ] operator overflow - [ ] finish operator type-checking -- [ ] Column path - [ ] Ranges - [ ] Source - [ ] Autoenv diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index ea85f52f71..dab0bf846d 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,6 +1,9 @@ use std::time::Instant; -use crate::{state::State, value::Value}; +use crate::{ + state::State, + value::{IntoRowStream, IntoValueStream, Value}, +}; use nu_parser::{Block, Call, Expr, Expression, Operator, Span, Statement, Type}; #[derive(Debug)] @@ -124,7 +127,7 @@ fn eval_call(state: &State, call: &Call) -> Result { for expr in &call.positional { let val = eval_expression(state, expr)?; - output.push(val.to_string()); + output.push(val.into_string()); } Ok(Value::String { val: output.join(""), @@ -259,7 +262,7 @@ pub fn eval_expression(state: &State, expr: &Expression) -> Result Result>>); + +impl ValueStream { + pub fn into_string(self) -> String { + let val: Vec = self.collect(); + format!( + "[{}]", + val.into_iter() + .map(|x| x.into_string()) + .collect::>() + .join(", ".into()) + ) + } +} + +impl Debug for ValueStream { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ValueStream").finish() + } +} + +impl Iterator for ValueStream { + type Item = Value; + + fn next(&mut self) -> Option { + { + let mut iter = self.0.borrow_mut(); + iter.next() + } + } +} + +pub trait IntoValueStream { + fn into_value_stream(self) -> ValueStream; +} + +impl IntoValueStream for Vec { + fn into_value_stream(self) -> ValueStream { + ValueStream(Rc::new(RefCell::new(self.into_iter()))) + } +} + +#[derive(Clone)] +pub struct RowStream(Rc>>>); + +impl RowStream { + pub fn into_string(self, headers: Vec) -> String { + let val: Vec> = self.collect(); + format!( + "[{}]\n[{}]", + headers + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(", ".into()), + val.into_iter() + .map(|x| { + x.into_iter() + .map(|x| x.into_string()) + .collect::>() + .join(", ".into()) + }) + .collect::>() + .join("\n") + ) + } +} + +impl Debug for RowStream { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ValueStream").finish() + } +} + +impl Iterator for RowStream { + type Item = Vec; + + fn next(&mut self) -> Option { + { + let mut iter = self.0.borrow_mut(); + iter.next() + } + } +} + +pub trait IntoRowStream { + fn into_row_stream(self) -> RowStream; +} + +impl IntoRowStream for Vec> { + fn into_row_stream(self) -> RowStream { + RowStream(Rc::new(RefCell::new(self.into_iter()))) + } +} + #[derive(Debug, Clone)] pub enum Value { Bool { @@ -23,12 +119,12 @@ pub enum Value { span: Span, }, List { - val: Vec, + val: ValueStream, span: Span, }, Table { headers: Vec, - val: Vec>, + val: RowStream, span: Span, }, Block { @@ -88,6 +184,19 @@ impl Value { Value::Block { .. } => Type::Block, } } + + pub fn into_string(self) -> String { + match self { + Value::Bool { val, .. } => val.to_string(), + Value::Int { val, .. } => val.to_string(), + Value::Float { val, .. } => val.to_string(), + Value::String { val, .. } => val, + Value::List { val, .. } => val.into_string(), + Value::Table { headers, val, .. } => val.into_string(headers), + Value::Block { val, .. } => format!("", val), + Value::Nothing { .. } => format!(""), + } + } } impl PartialEq for Value { @@ -97,62 +206,12 @@ impl PartialEq for Value { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => lhs == rhs, (Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => lhs == rhs, (Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => lhs == rhs, - (Value::List { val: l1, .. }, Value::List { val: l2, .. }) => l1 == l2, (Value::Block { val: b1, .. }, Value::Block { val: b2, .. }) => b1 == b2, _ => false, } } } -impl Display for Value { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Value::Bool { val, .. } => { - write!(f, "{}", val) - } - Value::Int { val, .. } => { - write!(f, "{}", val) - } - Value::Float { val, .. } => { - write!(f, "{}", val) - } - Value::String { val, .. } => write!(f, "{}", val), - Value::List { val, .. } => { - write!( - f, - "[{}]", - val.iter() - .map(|x| x.to_string()) - .collect::>() - .join(", ".into()) - ) - } - Value::Table { headers, val, .. } => { - write!( - f, - "[{}]\n[{}]", - headers - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(", ".into()), - val.iter() - .map(|x| { - x.iter() - .map(|x| x.to_string()) - .collect::>() - .join(", ".into()) - }) - .collect::>() - .join("\n") - ) - } - Value::Block { .. } => write!(f, ""), - Value::Nothing { .. } => write!(f, ""), - } - } -} - impl Value { pub fn add(&self, op: Span, rhs: &Value) -> Result { let span = nu_parser::span(&[self.span(), rhs.span()]); diff --git a/src/main.rs b/src/main.rs index 789963ef3c..6e29c85948 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,7 @@ fn main() -> std::io::Result<()> { match eval_block(&state, &block) { Ok(value) => { - println!("{}", value); + println!("{}", value.into_string()); } Err(err) => { let parser_state = parser_state.borrow(); @@ -94,7 +94,7 @@ fn main() -> std::io::Result<()> { match eval_block(&state, &block) { Ok(value) => { - println!("{}", value); + println!("{}", value.into_string()); } Err(err) => { let parser_state = parser_state.borrow();