mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 12:46:00 +02:00
Add a few operators. Needs parser work
This commit is contained in:
@ -16,6 +16,7 @@ pub enum ShellError {
|
||||
InternalError(String),
|
||||
VariableNotFound(Span),
|
||||
CantConvert(String, Span),
|
||||
DivisionByZero(Span),
|
||||
}
|
||||
|
||||
pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
|
||||
@ -227,7 +228,16 @@ pub fn eval_expression(state: &State, expr: &Expression) -> Result<Value, ShellE
|
||||
|
||||
match op {
|
||||
Operator::Plus => lhs.add(op_span, &rhs),
|
||||
_ => Ok(Value::Nothing { span: expr.span }),
|
||||
Operator::Minus => lhs.sub(op_span, &rhs),
|
||||
Operator::Multiply => lhs.mul(op_span, &rhs),
|
||||
Operator::Divide => lhs.div(op_span, &rhs),
|
||||
Operator::LessThan => lhs.lt(op_span, &rhs),
|
||||
Operator::LessThanOrEqual => lhs.lte(op_span, &rhs),
|
||||
Operator::GreaterThan => lhs.gt(op_span, &rhs),
|
||||
Operator::GreaterThanOrEqual => lhs.gte(op_span, &rhs),
|
||||
Operator::Equal => lhs.eq(op_span, &rhs),
|
||||
Operator::NotEqual => lhs.ne(op_span, &rhs),
|
||||
_ => Err(ShellError::Unsupported(op_span)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,4 +131,306 @@ impl Value {
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn sub(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||
if *rhs != 0 {
|
||||
Ok(Value::Int {
|
||||
val: lhs / rhs,
|
||||
span,
|
||||
})
|
||||
} 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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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,
|
||||
}),
|
||||
_ => 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> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
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,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user