forked from extern/nushell
Merge pull request #34 from moonrise-tk/main
Move value into its own folder in nu-protocol and add some comments
This commit is contained in:
commit
1e09a8e5ff
@ -1,4 +1,4 @@
|
|||||||
use crate::{ast::Call, BlockId, Example, ShellError, Signature, Value};
|
use crate::{ast::Call, value::Value, BlockId, Example, ShellError, Signature};
|
||||||
|
|
||||||
use super::EvaluationContext;
|
use super::EvaluationContext;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ mod span;
|
|||||||
mod syntax_shape;
|
mod syntax_shape;
|
||||||
mod ty;
|
mod ty;
|
||||||
mod value;
|
mod value;
|
||||||
|
pub use value::Value;
|
||||||
|
|
||||||
pub use example::*;
|
pub use example::*;
|
||||||
pub use id::*;
|
pub use id::*;
|
||||||
|
@ -1,230 +1,19 @@
|
|||||||
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
mod range;
|
||||||
|
mod row;
|
||||||
|
mod stream;
|
||||||
|
|
||||||
|
pub use range::*;
|
||||||
|
pub use row::*;
|
||||||
|
pub use stream::*;
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::ast::{PathMember, RangeInclusion};
|
use crate::ast::{PathMember, RangeInclusion};
|
||||||
use crate::{span, BlockId, Span, Type};
|
use crate::{span, BlockId, Span, Type};
|
||||||
|
|
||||||
use crate::ShellError;
|
use crate::ShellError;
|
||||||
|
|
||||||
#[derive(Clone)]
|
/// Core structured values that pass through the pipeline in engine-q
|
||||||
pub struct ValueStream(pub Rc<RefCell<dyn Iterator<Item = Value>>>);
|
|
||||||
|
|
||||||
impl ValueStream {
|
|
||||||
pub fn into_string(self) -> String {
|
|
||||||
format!(
|
|
||||||
"[{}]",
|
|
||||||
self.map(|x| x.into_string())
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_stream(input: impl Iterator<Item = Value> + 'static) -> ValueStream {
|
|
||||||
ValueStream(Rc::new(RefCell::new(input)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Self::Item> {
|
|
||||||
{
|
|
||||||
let mut iter = self.0.borrow_mut();
|
|
||||||
iter.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IntoValueStream {
|
|
||||||
fn into_value_stream(self) -> ValueStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> IntoValueStream for T
|
|
||||||
where
|
|
||||||
T: Iterator<Item = Value> + 'static,
|
|
||||||
{
|
|
||||||
fn into_value_stream(self) -> ValueStream {
|
|
||||||
ValueStream::from_stream(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct RowStream(Rc<RefCell<dyn Iterator<Item = Vec<Value>>>>);
|
|
||||||
|
|
||||||
impl RowStream {
|
|
||||||
pub fn into_string(self, headers: Vec<String>) -> String {
|
|
||||||
format!(
|
|
||||||
"[{}]\n[{}]",
|
|
||||||
headers
|
|
||||||
.iter()
|
|
||||||
.map(|x| x.to_string())
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", "),
|
|
||||||
self.map(|x| {
|
|
||||||
x.into_iter()
|
|
||||||
.map(|x| x.into_string())
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", ")
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.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<Value>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
{
|
|
||||||
let mut iter = self.0.borrow_mut();
|
|
||||||
iter.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IntoRowStream {
|
|
||||||
fn into_row_stream(self) -> RowStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoRowStream for Vec<Vec<Value>> {
|
|
||||||
fn into_row_stream(self) -> RowStream {
|
|
||||||
RowStream(Rc::new(RefCell::new(self.into_iter())))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct Range {
|
|
||||||
pub from: Value,
|
|
||||||
pub to: Value,
|
|
||||||
pub inclusion: RangeInclusion,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoIterator for Range {
|
|
||||||
type Item = Value;
|
|
||||||
|
|
||||||
type IntoIter = RangeIterator;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
let span = self.from.span();
|
|
||||||
|
|
||||||
RangeIterator::new(self, span)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RangeIterator {
|
|
||||||
curr: Value,
|
|
||||||
end: Value,
|
|
||||||
span: Span,
|
|
||||||
is_end_inclusive: bool,
|
|
||||||
moves_up: bool,
|
|
||||||
one: Value,
|
|
||||||
negative_one: Value,
|
|
||||||
done: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RangeIterator {
|
|
||||||
pub fn new(range: Range, span: Span) -> RangeIterator {
|
|
||||||
let start = match range.from {
|
|
||||||
Value::Nothing { .. } => Value::Int { val: 0, span },
|
|
||||||
x => x,
|
|
||||||
};
|
|
||||||
|
|
||||||
let end = match range.to {
|
|
||||||
Value::Nothing { .. } => Value::Int {
|
|
||||||
val: i64::MAX,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
x => x,
|
|
||||||
};
|
|
||||||
|
|
||||||
RangeIterator {
|
|
||||||
moves_up: matches!(start.lte(span, &end), Ok(Value::Bool { val: true, .. })),
|
|
||||||
curr: start,
|
|
||||||
end,
|
|
||||||
span,
|
|
||||||
is_end_inclusive: matches!(range.inclusion, RangeInclusion::Inclusive),
|
|
||||||
done: false,
|
|
||||||
one: Value::Int { val: 1, span },
|
|
||||||
negative_one: Value::Int { val: -1, span },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for RangeIterator {
|
|
||||||
type Item = Value;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
if self.done {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ordering = if matches!(self.end, Value::Nothing { .. }) {
|
|
||||||
Ordering::Less
|
|
||||||
} else {
|
|
||||||
match (&self.curr, &self.end) {
|
|
||||||
(Value::Int { val: x, .. }, Value::Int { val: y, .. }) => x.cmp(y),
|
|
||||||
// (Value::Float { val: x, .. }, Value::Float { val: y, .. }) => x.cmp(y),
|
|
||||||
// (Value::Float { val: x, .. }, Value::Int { val: y, .. }) => x.cmp(y),
|
|
||||||
// (Value::Int { val: x, .. }, Value::Float { val: y, .. }) => x.cmp(y),
|
|
||||||
_ => {
|
|
||||||
self.done = true;
|
|
||||||
return Some(Value::Error {
|
|
||||||
error: ShellError::CannotCreateRange(self.span),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.moves_up
|
|
||||||
&& (ordering == Ordering::Less || self.is_end_inclusive && ordering == Ordering::Equal)
|
|
||||||
{
|
|
||||||
let next_value = self.curr.add(self.span, &self.one);
|
|
||||||
|
|
||||||
let mut next = match next_value {
|
|
||||||
Ok(result) => result,
|
|
||||||
|
|
||||||
Err(error) => {
|
|
||||||
self.done = true;
|
|
||||||
return Some(Value::Error { error });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::mem::swap(&mut self.curr, &mut next);
|
|
||||||
|
|
||||||
Some(next)
|
|
||||||
} else if !self.moves_up
|
|
||||||
&& (ordering == Ordering::Greater
|
|
||||||
|| self.is_end_inclusive && ordering == Ordering::Equal)
|
|
||||||
{
|
|
||||||
let next_value = self.curr.add(self.span, &self.negative_one);
|
|
||||||
|
|
||||||
let mut next = match next_value {
|
|
||||||
Ok(result) => result,
|
|
||||||
Err(error) => {
|
|
||||||
self.done = true;
|
|
||||||
return Some(Value::Error { error });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::mem::swap(&mut self.curr, &mut next);
|
|
||||||
|
|
||||||
Some(next)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Bool {
|
Bool {
|
||||||
@ -280,8 +69,10 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the span for the current value
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
|
Value::Error { .. } => Span::unknown(),
|
||||||
Value::Bool { span, .. } => *span,
|
Value::Bool { span, .. } => *span,
|
||||||
Value::Int { span, .. } => *span,
|
Value::Int { span, .. } => *span,
|
||||||
Value::Float { span, .. } => *span,
|
Value::Float { span, .. } => *span,
|
||||||
@ -292,10 +83,10 @@ impl Value {
|
|||||||
Value::Block { span, .. } => *span,
|
Value::Block { span, .. } => *span,
|
||||||
Value::Stream { span, .. } => *span,
|
Value::Stream { span, .. } => *span,
|
||||||
Value::Nothing { span, .. } => *span,
|
Value::Nothing { span, .. } => *span,
|
||||||
Value::Error { .. } => Span::unknown(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the value with a new span
|
||||||
pub fn with_span(mut self, new_span: Span) -> Value {
|
pub fn with_span(mut self, new_span: Span) -> Value {
|
||||||
match &mut self {
|
match &mut self {
|
||||||
Value::Bool { span, .. } => *span = new_span,
|
Value::Bool { span, .. } => *span = new_span,
|
||||||
@ -314,6 +105,7 @@ impl Value {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the type of the current Value
|
||||||
pub fn get_type(&self) -> Type {
|
pub fn get_type(&self) -> Type {
|
||||||
match self {
|
match self {
|
||||||
Value::Bool { .. } => Type::Bool,
|
Value::Bool { .. } => Type::Bool,
|
||||||
@ -332,6 +124,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert Value into string. Note that Streams will be consumed.
|
||||||
pub fn into_string(self) -> String {
|
pub fn into_string(self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Value::Bool { val, .. } => val.to_string(),
|
Value::Bool { val, .. } => val.to_string(),
|
||||||
@ -379,6 +172,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new `Nothing` value
|
||||||
pub fn nothing() -> Value {
|
pub fn nothing() -> Value {
|
||||||
Value::Nothing {
|
Value::Nothing {
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
122
crates/nu-protocol/src/value/range.rs
Normal file
122
crates/nu-protocol/src/value/range.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
use crate::{ast::RangeInclusion, *};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Range {
|
||||||
|
pub from: Value,
|
||||||
|
pub to: Value,
|
||||||
|
pub inclusion: RangeInclusion,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for Range {
|
||||||
|
type Item = Value;
|
||||||
|
|
||||||
|
type IntoIter = RangeIterator;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
let span = self.from.span();
|
||||||
|
|
||||||
|
RangeIterator::new(self, span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RangeIterator {
|
||||||
|
curr: Value,
|
||||||
|
end: Value,
|
||||||
|
span: Span,
|
||||||
|
is_end_inclusive: bool,
|
||||||
|
moves_up: bool,
|
||||||
|
one: Value,
|
||||||
|
negative_one: Value,
|
||||||
|
done: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RangeIterator {
|
||||||
|
pub fn new(range: Range, span: Span) -> RangeIterator {
|
||||||
|
let start = match range.from {
|
||||||
|
Value::Nothing { .. } => Value::Int { val: 0, span },
|
||||||
|
x => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
let end = match range.to {
|
||||||
|
Value::Nothing { .. } => Value::Int {
|
||||||
|
val: i64::MAX,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
x => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
RangeIterator {
|
||||||
|
moves_up: matches!(start.lte(span, &end), Ok(Value::Bool { val: true, .. })),
|
||||||
|
curr: start,
|
||||||
|
end,
|
||||||
|
span,
|
||||||
|
is_end_inclusive: matches!(range.inclusion, RangeInclusion::Inclusive),
|
||||||
|
done: false,
|
||||||
|
one: Value::Int { val: 1, span },
|
||||||
|
negative_one: Value::Int { val: -1, span },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for RangeIterator {
|
||||||
|
type Item = Value;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
if self.done {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ordering = if matches!(self.end, Value::Nothing { .. }) {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
match (&self.curr, &self.end) {
|
||||||
|
(Value::Int { val: x, .. }, Value::Int { val: y, .. }) => x.cmp(y),
|
||||||
|
// (Value::Float { val: x, .. }, Value::Float { val: y, .. }) => x.cmp(y),
|
||||||
|
// (Value::Float { val: x, .. }, Value::Int { val: y, .. }) => x.cmp(y),
|
||||||
|
// (Value::Int { val: x, .. }, Value::Float { val: y, .. }) => x.cmp(y),
|
||||||
|
_ => {
|
||||||
|
self.done = true;
|
||||||
|
return Some(Value::Error {
|
||||||
|
error: ShellError::CannotCreateRange(self.span),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.moves_up
|
||||||
|
&& (ordering == Ordering::Less || self.is_end_inclusive && ordering == Ordering::Equal)
|
||||||
|
{
|
||||||
|
let next_value = self.curr.add(self.span, &self.one);
|
||||||
|
|
||||||
|
let mut next = match next_value {
|
||||||
|
Ok(result) => result,
|
||||||
|
|
||||||
|
Err(error) => {
|
||||||
|
self.done = true;
|
||||||
|
return Some(Value::Error { error });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::mem::swap(&mut self.curr, &mut next);
|
||||||
|
|
||||||
|
Some(next)
|
||||||
|
} else if !self.moves_up
|
||||||
|
&& (ordering == Ordering::Greater
|
||||||
|
|| self.is_end_inclusive && ordering == Ordering::Equal)
|
||||||
|
{
|
||||||
|
let next_value = self.curr.add(self.span, &self.negative_one);
|
||||||
|
|
||||||
|
let mut next = match next_value {
|
||||||
|
Ok(result) => result,
|
||||||
|
Err(error) => {
|
||||||
|
self.done = true;
|
||||||
|
return Some(Value::Error { error });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::mem::swap(&mut self.curr, &mut next);
|
||||||
|
|
||||||
|
Some(next)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
crates/nu-protocol/src/value/row.rs
Normal file
54
crates/nu-protocol/src/value/row.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RowStream(Rc<RefCell<dyn Iterator<Item = Vec<Value>>>>);
|
||||||
|
|
||||||
|
impl RowStream {
|
||||||
|
pub fn into_string(self, headers: Vec<String>) -> String {
|
||||||
|
format!(
|
||||||
|
"[{}]\n[{}]",
|
||||||
|
headers
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(", "),
|
||||||
|
self.map(|x: Vec<Value>| {
|
||||||
|
x.into_iter()
|
||||||
|
.map(|x| x.into_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(", ")
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.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<Value>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
{
|
||||||
|
let mut iter = self.0.borrow_mut();
|
||||||
|
iter.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait IntoRowStream {
|
||||||
|
fn into_row_stream(self) -> RowStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoRowStream for Vec<Vec<Value>> {
|
||||||
|
fn into_row_stream(self) -> RowStream {
|
||||||
|
RowStream(Rc::new(RefCell::new(self.into_iter())))
|
||||||
|
}
|
||||||
|
}
|
50
crates/nu-protocol/src/value/stream.rs
Normal file
50
crates/nu-protocol/src/value/stream.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use crate::*;
|
||||||
|
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ValueStream(pub Rc<RefCell<dyn Iterator<Item = Value>>>);
|
||||||
|
|
||||||
|
impl ValueStream {
|
||||||
|
pub fn into_string(self) -> String {
|
||||||
|
format!(
|
||||||
|
"[{}]",
|
||||||
|
self.map(|x: Value| x.into_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_stream(input: impl Iterator<Item = Value> + 'static) -> ValueStream {
|
||||||
|
ValueStream(Rc::new(RefCell::new(input)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Self::Item> {
|
||||||
|
{
|
||||||
|
let mut iter = self.0.borrow_mut();
|
||||||
|
iter.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait IntoValueStream {
|
||||||
|
fn into_value_stream(self) -> ValueStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IntoValueStream for T
|
||||||
|
where
|
||||||
|
T: Iterator<Item = Value> + 'static,
|
||||||
|
{
|
||||||
|
fn into_value_stream(self) -> ValueStream {
|
||||||
|
ValueStream::from_stream(self)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user