nushell/crates/nu-protocol/src/value/mod.rs

752 lines
26 KiB
Rust
Raw Normal View History

2021-09-08 04:26:57 +02:00
mod range;
mod row;
mod stream;
pub use range::*;
pub use row::*;
2021-10-01 07:11:49 +02:00
use serde::{Deserialize, Serialize};
2021-09-08 04:26:57 +02:00
pub use stream::*;
2021-09-08 04:32:28 +02:00
use std::fmt::Debug;
2021-08-16 00:33:34 +02:00
2021-10-02 04:59:11 +02:00
use crate::ast::{CellPath, PathMember};
2021-09-02 03:29:43 +02:00
use crate::{span, BlockId, Span, Type};
2021-08-16 00:33:34 +02:00
use crate::ShellError;
2021-09-08 04:26:57 +02:00
/// Core structured values that pass through the pipeline in engine-q
2021-10-01 07:11:49 +02:00
#[derive(Debug, Clone, Serialize, Deserialize)]
2021-08-16 00:33:34 +02:00
pub enum Value {
2021-08-28 21:17:30 +02:00
Bool {
val: bool,
span: Span,
},
Int {
val: i64,
span: Span,
},
2021-10-01 08:53:47 +02:00
Filesize {
val: u64,
span: Span,
},
2021-10-01 23:53:13 +02:00
Duration {
val: u64,
span: Span,
},
Range {
val: Box<Range>,
span: Span,
},
2021-08-28 21:17:30 +02:00
Float {
val: f64,
span: Span,
},
String {
val: String,
span: Span,
},
Record {
cols: Vec<String>,
vals: Vec<Value>,
2021-09-04 08:52:28 +02:00
span: Span,
},
2021-09-07 09:35:59 +02:00
Stream {
stream: ValueStream,
2021-09-04 08:52:28 +02:00
span: Span,
},
2021-08-28 21:17:30 +02:00
List {
vals: Vec<Value>,
2021-08-28 21:17:30 +02:00
span: Span,
},
Block {
val: BlockId,
span: Span,
},
Nothing {
span: Span,
},
2021-09-06 01:16:27 +02:00
Error {
2021-09-06 06:07:48 +02:00
error: ShellError,
2021-09-06 01:16:27 +02:00
},
2021-09-23 18:42:03 +02:00
Binary {
val: Vec<u8>,
span: Span,
},
2021-10-02 04:59:11 +02:00
CellPath {
val: CellPath,
span: Span,
},
2021-08-16 00:33:34 +02:00
}
impl Value {
pub fn as_string(&self) -> Result<String, ShellError> {
match self {
Value::String { val, .. } => Ok(val.to_string()),
_ => Err(ShellError::CantConvert("string".into(), self.span())),
}
}
2021-09-08 04:26:57 +02:00
/// Get the span for the current value
2021-08-16 00:33:34 +02:00
pub fn span(&self) -> Span {
match self {
2021-09-08 04:26:57 +02:00
Value::Error { .. } => Span::unknown(),
2021-08-16 00:33:34 +02:00
Value::Bool { span, .. } => *span,
Value::Int { span, .. } => *span,
Value::Float { span, .. } => *span,
2021-10-01 08:53:47 +02:00
Value::Filesize { span, .. } => *span,
2021-10-01 23:53:13 +02:00
Value::Duration { span, .. } => *span,
Value::Range { span, .. } => *span,
2021-08-16 00:33:34 +02:00
Value::String { span, .. } => *span,
Value::Record { span, .. } => *span,
2021-08-16 00:33:34 +02:00
Value::List { span, .. } => *span,
Value::Block { span, .. } => *span,
2021-09-07 09:35:59 +02:00
Value::Stream { span, .. } => *span,
2021-08-16 00:33:34 +02:00
Value::Nothing { span, .. } => *span,
2021-09-23 18:42:03 +02:00
Value::Binary { span, .. } => *span,
2021-10-02 04:59:11 +02:00
Value::CellPath { span, .. } => *span,
2021-08-16 00:33:34 +02:00
}
}
2021-09-08 04:26:57 +02:00
/// Update the value with a new span
2021-08-16 00:33:34 +02:00
pub fn with_span(mut self, new_span: Span) -> Value {
match &mut self {
Value::Bool { span, .. } => *span = new_span,
Value::Int { span, .. } => *span = new_span,
Value::Float { span, .. } => *span = new_span,
2021-10-01 08:53:47 +02:00
Value::Filesize { span, .. } => *span = new_span,
2021-10-01 23:53:13 +02:00
Value::Duration { span, .. } => *span = new_span,
Value::Range { span, .. } => *span = new_span,
2021-08-16 00:33:34 +02:00
Value::String { span, .. } => *span = new_span,
Value::Record { span, .. } => *span = new_span,
2021-09-07 09:35:59 +02:00
Value::Stream { span, .. } => *span = new_span,
2021-08-16 00:33:34 +02:00
Value::List { span, .. } => *span = new_span,
Value::Block { span, .. } => *span = new_span,
Value::Nothing { span, .. } => *span = new_span,
2021-09-06 01:16:27 +02:00
Value::Error { .. } => {}
2021-09-23 18:42:03 +02:00
Value::Binary { span, .. } => *span = new_span,
2021-10-02 04:59:11 +02:00
Value::CellPath { span, .. } => *span = new_span,
2021-08-16 00:33:34 +02:00
}
self
}
2021-09-08 04:26:57 +02:00
/// Get the type of the current Value
2021-08-16 00:33:34 +02:00
pub fn get_type(&self) -> Type {
match self {
Value::Bool { .. } => Type::Bool,
Value::Int { .. } => Type::Int,
Value::Float { .. } => Type::Float,
2021-10-01 08:53:47 +02:00
Value::Filesize { .. } => Type::Filesize,
2021-10-01 23:53:13 +02:00
Value::Duration { .. } => Type::Duration,
Value::Range { .. } => Type::Range,
2021-08-16 00:33:34 +02:00
Value::String { .. } => Type::String,
Value::Record { cols, vals, .. } => {
Type::Record(cols.clone(), vals.iter().map(|x| x.get_type()).collect())
}
2021-08-16 00:33:34 +02:00
Value::List { .. } => Type::List(Box::new(Type::Unknown)), // FIXME
Value::Nothing { .. } => Type::Nothing,
Value::Block { .. } => Type::Block,
2021-09-07 09:35:59 +02:00
Value::Stream { .. } => Type::ValueStream,
2021-09-06 01:16:27 +02:00
Value::Error { .. } => Type::Error,
2021-09-23 18:42:03 +02:00
Value::Binary { .. } => Type::Binary,
2021-10-02 04:59:11 +02:00
Value::CellPath { .. } => Type::CellPath,
2021-08-16 00:33:34 +02:00
}
}
2021-09-01 23:20:53 +02:00
2021-09-08 04:26:57 +02:00
/// Convert Value into string. Note that Streams will be consumed.
2021-09-01 23:20:53 +02:00
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(),
2021-10-01 08:53:47 +02:00
Value::Filesize { val, .. } => format!("{} bytes", val),
2021-10-01 23:53:13 +02:00
Value::Duration { val, .. } => format!("{} ns", val),
Value::Range { val, .. } => {
format!(
"range: [{}]",
val.into_iter()
.map(|x| x.into_string())
.collect::<Vec<String>>()
2021-09-05 00:40:15 +02:00
.join(", ")
)
2021-09-05 00:35:08 +02:00
}
2021-09-01 23:20:53 +02:00
Value::String { val, .. } => val,
2021-09-07 09:35:59 +02:00
Value::Stream { stream, .. } => stream.into_string(),
Value::List { vals: val, .. } => format!(
2021-09-07 00:02:24 +02:00
"[{}]",
val.into_iter()
.map(|x| x.into_string())
.collect::<Vec<_>>()
.join(", ")
),
Value::Record { cols, vals, .. } => format!(
"{{{}}}",
cols.iter()
.zip(vals.iter())
.map(|(x, y)| format!("{}: {}", x, y.clone().into_string()))
2021-09-07 00:02:24 +02:00
.collect::<Vec<_>>()
.join(", ")
2021-09-07 00:02:24 +02:00
),
2021-09-01 23:20:53 +02:00
Value::Block { val, .. } => format!("<Block {}>", val),
2021-09-02 03:29:43 +02:00
Value::Nothing { .. } => String::new(),
2021-09-06 06:07:48 +02:00
Value::Error { error } => format!("{:?}", error),
2021-09-23 18:42:03 +02:00
Value::Binary { val, .. } => format!("{:?}", val),
2021-10-02 04:59:11 +02:00
Value::CellPath { val, .. } => format!("{:?}", val),
2021-10-01 08:01:22 +02:00
}
}
pub fn collect_string(self) -> String {
match self {
Value::Bool { val, .. } => val.to_string(),
Value::Int { val, .. } => val.to_string(),
Value::Float { val, .. } => val.to_string(),
2021-10-01 08:53:47 +02:00
Value::Filesize { val, .. } => format!("{} bytes", val),
2021-10-01 23:53:13 +02:00
Value::Duration { val, .. } => format!("{} ns", val),
2021-10-01 08:01:22 +02:00
Value::Range { val, .. } => val
.into_iter()
.map(|x| x.into_string())
.collect::<Vec<String>>()
.join(", "),
Value::String { val, .. } => val,
Value::Stream { stream, .. } => stream.collect_string(),
Value::List { vals: val, .. } => val
.into_iter()
.map(|x| x.collect_string())
.collect::<Vec<_>>()
.join("\n"),
Value::Record { vals, .. } => vals
.into_iter()
.map(|y| y.collect_string())
.collect::<Vec<_>>()
.join("\n"),
Value::Block { val, .. } => format!("<Block {}>", val),
Value::Nothing { .. } => String::new(),
Value::Error { error } => format!("{:?}", error),
Value::Binary { val, .. } => format!("{:?}", val),
2021-10-02 04:59:11 +02:00
Value::CellPath { val, .. } => format!("{:?}", val),
2021-09-01 23:20:53 +02:00
}
}
2021-09-03 04:15:01 +02:00
2021-09-08 04:26:57 +02:00
/// Create a new `Nothing` value
2021-09-03 04:15:01 +02:00
pub fn nothing() -> Value {
Value::Nothing {
span: Span::unknown(),
}
}
2021-09-07 00:02:24 +02:00
2021-09-26 20:39:19 +02:00
pub fn follow_cell_path(self, cell_path: &[PathMember]) -> Result<Value, ShellError> {
2021-09-07 00:02:24 +02:00
let mut current = self;
2021-09-26 20:39:19 +02:00
for member in cell_path {
2021-09-07 00:02:24 +02:00
// FIXME: this uses a few extra clones for simplicity, but there may be a way
// to traverse the path without them
match member {
PathMember::Int {
val: count,
span: origin_span,
} => {
// Treat a numeric path member as `nth <val>`
match &mut current {
Value::List { vals: val, .. } => {
2021-09-07 00:02:24 +02:00
if let Some(item) = val.get(*count) {
current = item.clone();
} else {
return Err(ShellError::AccessBeyondEnd(val.len(), *origin_span));
}
}
2021-09-07 09:35:59 +02:00
Value::Stream { stream, .. } => {
2021-09-07 00:02:24 +02:00
if let Some(item) = stream.nth(*count) {
current = item;
} else {
return Err(ShellError::AccessBeyondEndOfStream(*origin_span));
}
}
x => {
return Err(ShellError::IncompatiblePathAccess(
format!("{}", x.get_type()),
*origin_span,
))
}
}
}
PathMember::String {
val: column_name,
2021-09-07 00:02:24 +02:00
span: origin_span,
} => match &mut current {
Value::Record { cols, vals, .. } => {
2021-09-07 00:02:24 +02:00
let mut found = false;
for col in cols.iter().zip(vals.iter()) {
if col.0 == column_name {
current = col.1.clone();
2021-09-07 00:02:24 +02:00
found = true;
break;
}
}
if !found {
return Err(ShellError::CantFindColumn(*origin_span));
}
}
Value::List { vals, span } => {
let mut output = vec![];
for val in vals {
if let Value::Record { cols, vals, .. } = val {
for col in cols.iter().enumerate() {
if col.1 == column_name {
output.push(vals[col.0].clone());
}
2021-09-07 09:35:59 +02:00
}
}
}
current = Value::List {
vals: output,
span: *span,
};
}
Value::Stream { stream, span } => {
let mut output = vec![];
for val in stream {
if let Value::Record { cols, vals, .. } = val {
for col in cols.iter().enumerate() {
if col.1 == column_name {
output.push(vals[col.0].clone());
}
2021-09-07 00:02:24 +02:00
}
}
}
current = Value::List {
vals: output,
span: *span,
};
2021-09-07 00:02:24 +02:00
}
x => {
return Err(ShellError::IncompatiblePathAccess(
format!("{}", x.get_type()),
*origin_span,
))
}
},
}
}
Ok(current)
}
2021-09-09 23:47:20 +02:00
2021-09-10 03:06:44 +02:00
pub fn string(s: &str, span: Span) -> Value {
Value::String {
val: s.into(),
span,
}
}
2021-09-09 23:47:20 +02:00
pub fn is_true(&self) -> bool {
matches!(self, Value::Bool { val: true, .. })
}
2021-09-10 04:27:12 +02:00
pub fn columns(&self) -> Vec<String> {
match self {
Value::Record { cols, .. } => cols.clone(),
_ => vec![],
}
}
2021-08-16 00:33:34 +02:00
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Bool { val: lhs, .. }, Value::Bool { val: rhs, .. }) => lhs == rhs,
(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::Block { val: b1, .. }, Value::Block { val: b2, .. }) => b1 == b2,
_ => false,
}
}
}
impl Value {
pub fn add(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-16 00:33:34 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
val: lhs + rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: *lhs as f64 + *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
val: *lhs + *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: lhs + rhs,
span,
}),
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::String {
val: lhs.to_string() + rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
2021-08-25 21:29:36 +02:00
pub fn sub(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
val: lhs - rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: *lhs as f64 - *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
val: *lhs - *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: lhs - rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn mul(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
val: lhs * rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: *lhs as f64 * *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
val: *lhs * *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: lhs * rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn div(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
if *rhs != 0 {
if lhs % rhs == 0 {
Ok(Value::Int {
val: lhs / rhs,
span,
})
} else {
Ok(Value::Float {
val: (*lhs as f64) / (*rhs as f64),
span,
})
}
2021-08-25 21:29:36 +02:00
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
if *rhs != 0.0 {
Ok(Value::Float {
val: *lhs as f64 / *rhs,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Float {
val: *lhs / *rhs as f64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
if *rhs != 0.0 {
Ok(Value::Float {
val: lhs / rhs,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn lt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: lhs < rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: (*lhs as f64) < *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: *lhs < *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: lhs < rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn lte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: lhs <= rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: (*lhs as f64) <= *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: *lhs <= *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: lhs <= rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn gt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: lhs > rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: (*lhs as f64) > *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: *lhs > *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: lhs > rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn gte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: lhs >= rhs,
span,
}),
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: (*lhs as f64) >= *rhs,
span,
}),
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: *lhs >= *rhs as f64,
span,
}),
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: lhs >= rhs,
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn eq(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: lhs == rhs,
span,
}),
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
val: lhs == rhs,
span,
}),
// FIXME: these should consider machine epsilon
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: (*lhs as f64) == *rhs,
span,
}),
// FIXME: these should consider machine epsilon
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: *lhs == *rhs as f64,
span,
}),
// FIXME: these should consider machine epsilon
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: lhs == rhs,
span,
}),
(Value::List { vals: lhs, .. }, Value::List { vals: rhs, .. }) => Ok(Value::Bool {
2021-09-04 08:52:28 +02:00
val: lhs == rhs,
span,
}),
(
Value::Record {
vals: lhs,
cols: lhs_headers,
2021-09-04 08:52:28 +02:00
..
},
Value::Record {
vals: rhs,
cols: rhs_headers,
2021-09-04 08:52:28 +02:00
..
},
) => Ok(Value::Bool {
val: lhs_headers == rhs_headers && lhs == rhs,
span,
}),
2021-08-25 21:29:36 +02:00
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
pub fn ne(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
2021-09-02 03:29:43 +02:00
let span = span(&[self.span(), rhs.span()]);
2021-08-25 21:29:36 +02:00
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: lhs != rhs,
span,
}),
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
val: lhs != rhs,
span,
}),
// FIXME: these should consider machine epsilon
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: (*lhs as f64) != *rhs,
span,
}),
// FIXME: these should consider machine epsilon
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
val: *lhs != *rhs as f64,
span,
}),
// FIXME: these should consider machine epsilon
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
val: lhs != rhs,
span,
}),
(Value::List { vals: lhs, .. }, Value::List { vals: rhs, .. }) => Ok(Value::Bool {
2021-09-04 08:52:28 +02:00
val: lhs != rhs,
span,
}),
(
Value::Record {
vals: lhs,
cols: lhs_headers,
2021-09-04 08:52:28 +02:00
..
},
Value::Record {
vals: rhs,
cols: rhs_headers,
2021-09-04 08:52:28 +02:00
..
},
) => Ok(Value::Bool {
val: lhs_headers != rhs_headers || lhs != rhs,
span,
}),
2021-08-25 21:29:36 +02:00
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
2021-08-16 00:33:34 +02:00
}