mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 09:25:38 +02:00
Limited mutable variables (#7089)
This adds support for (limited) mutable variables. Mutable variables are created with mut much the same way immutable variables are made with let. Mutable variables allow mutation via the assignment operator (=). ❯ mut x = 100 ❯ $x = 200 ❯ print $x 200 Mutable variables are limited in that they're only tended to be used in the local code block. Trying to capture a local variable will result in an error: ❯ mut x = 123; {|| $x } Error: nu::parser::expected_keyword (link) × Capture of mutable variable. The intent of this limitation is to reduce some of the issues with mutable variables in general: namely they make code that's harder to reason about. By reducing the scope that a mutable variable can be used it, we can help create local reasoning about them. Mutation can occur with fields as well, as in this case: ❯ mut y = {abc: 123} ❯ $y.abc = 456 ❯ $y On a historical note: mutable variables are something that we resisted for quite a long time, leaning as much as we could on the functional style of pipelines and dataflow. That said, we've watched folks struggle to work with reduce as an approximation for patterns that would be trivial to express with local mutation. With that in mind, we're leaning towards the happy path.
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Expr, Operator};
|
||||
use super::Expr;
|
||||
use crate::ast::ImportPattern;
|
||||
use crate::DeclId;
|
||||
use crate::{engine::StateWorkingSet, BlockId, Signature, Span, Type, VarId, IN_VARIABLE_ID};
|
||||
@ -26,34 +26,36 @@ impl Expression {
|
||||
pub fn precedence(&self) -> usize {
|
||||
match &self.expr {
|
||||
Expr::Operator(operator) => {
|
||||
use super::operator::*;
|
||||
// Higher precedence binds tighter
|
||||
|
||||
match operator {
|
||||
Operator::Pow => 100,
|
||||
Operator::Multiply
|
||||
| Operator::Divide
|
||||
| Operator::Modulo
|
||||
| Operator::FloorDivision => 95,
|
||||
Operator::Plus | Operator::Minus => 90,
|
||||
Operator::ShiftLeft | Operator::ShiftRight => 85,
|
||||
Operator::NotRegexMatch
|
||||
| Operator::RegexMatch
|
||||
| Operator::StartsWith
|
||||
| Operator::EndsWith
|
||||
| Operator::LessThan
|
||||
| Operator::LessThanOrEqual
|
||||
| Operator::GreaterThan
|
||||
| Operator::GreaterThanOrEqual
|
||||
| Operator::Equal
|
||||
| Operator::NotEqual
|
||||
| Operator::In
|
||||
| Operator::NotIn
|
||||
| Operator::Append => 80,
|
||||
Operator::BitAnd => 75,
|
||||
Operator::BitXor => 70,
|
||||
Operator::BitOr => 60,
|
||||
Operator::And => 50,
|
||||
Operator::Or => 40,
|
||||
Operator::Math(Math::Pow) => 100,
|
||||
Operator::Math(Math::Multiply)
|
||||
| Operator::Math(Math::Divide)
|
||||
| Operator::Math(Math::Modulo)
|
||||
| Operator::Math(Math::FloorDivision) => 95,
|
||||
Operator::Math(Math::Plus) | Operator::Math(Math::Minus) => 90,
|
||||
Operator::Bits(Bits::ShiftLeft) | Operator::Bits(Bits::ShiftRight) => 85,
|
||||
Operator::Comparison(Comparison::NotRegexMatch)
|
||||
| Operator::Comparison(Comparison::RegexMatch)
|
||||
| Operator::Comparison(Comparison::StartsWith)
|
||||
| Operator::Comparison(Comparison::EndsWith)
|
||||
| Operator::Comparison(Comparison::LessThan)
|
||||
| Operator::Comparison(Comparison::LessThanOrEqual)
|
||||
| Operator::Comparison(Comparison::GreaterThan)
|
||||
| Operator::Comparison(Comparison::GreaterThanOrEqual)
|
||||
| Operator::Comparison(Comparison::Equal)
|
||||
| Operator::Comparison(Comparison::NotEqual)
|
||||
| Operator::Comparison(Comparison::In)
|
||||
| Operator::Comparison(Comparison::NotIn)
|
||||
| Operator::Math(Math::Append) => 80,
|
||||
Operator::Bits(Bits::BitAnd) => 75,
|
||||
Operator::Bits(Bits::BitXor) => 70,
|
||||
Operator::Bits(Bits::BitOr) => 60,
|
||||
Operator::Boolean(Boolean::And) => 50,
|
||||
Operator::Boolean(Boolean::Or) => 40,
|
||||
Operator::Assignment(Assignment::Assign) => 10,
|
||||
}
|
||||
}
|
||||
_ => 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Operator {
|
||||
pub enum Comparison {
|
||||
Equal,
|
||||
NotEqual,
|
||||
LessThan,
|
||||
@ -13,20 +13,32 @@ pub enum Operator {
|
||||
GreaterThanOrEqual,
|
||||
RegexMatch,
|
||||
NotRegexMatch,
|
||||
In,
|
||||
NotIn,
|
||||
StartsWith,
|
||||
EndsWith,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Math {
|
||||
Plus,
|
||||
Append,
|
||||
Minus,
|
||||
Multiply,
|
||||
Divide,
|
||||
In,
|
||||
NotIn,
|
||||
Modulo,
|
||||
FloorDivision,
|
||||
Pow,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Boolean {
|
||||
And,
|
||||
Or,
|
||||
Pow,
|
||||
StartsWith,
|
||||
EndsWith,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Bits {
|
||||
BitOr,
|
||||
BitXor,
|
||||
BitAnd,
|
||||
@ -34,36 +46,51 @@ pub enum Operator {
|
||||
ShiftRight,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Assignment {
|
||||
Assign,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Operator {
|
||||
Comparison(Comparison),
|
||||
Math(Math),
|
||||
Boolean(Boolean),
|
||||
Bits(Bits),
|
||||
Assignment(Assignment),
|
||||
}
|
||||
|
||||
impl Display for Operator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Operator::Equal => write!(f, "=="),
|
||||
Operator::NotEqual => write!(f, "!="),
|
||||
Operator::LessThan => write!(f, "<"),
|
||||
Operator::GreaterThan => write!(f, ">"),
|
||||
Operator::RegexMatch => write!(f, "=~"),
|
||||
Operator::NotRegexMatch => write!(f, "!~"),
|
||||
Operator::Plus => write!(f, "+"),
|
||||
Operator::Append => write!(f, "++"),
|
||||
Operator::Minus => write!(f, "-"),
|
||||
Operator::Multiply => write!(f, "*"),
|
||||
Operator::Divide => write!(f, "/"),
|
||||
Operator::In => write!(f, "in"),
|
||||
Operator::NotIn => write!(f, "not-in"),
|
||||
Operator::Modulo => write!(f, "mod"),
|
||||
Operator::FloorDivision => write!(f, "fdiv"),
|
||||
Operator::And => write!(f, "&&"),
|
||||
Operator::Or => write!(f, "||"),
|
||||
Operator::Pow => write!(f, "**"),
|
||||
Operator::BitOr => write!(f, "bit-or"),
|
||||
Operator::BitXor => write!(f, "bit-xor"),
|
||||
Operator::BitAnd => write!(f, "bit-and"),
|
||||
Operator::ShiftLeft => write!(f, "bit-shl"),
|
||||
Operator::ShiftRight => write!(f, "bit-shr"),
|
||||
Operator::LessThanOrEqual => write!(f, "<="),
|
||||
Operator::GreaterThanOrEqual => write!(f, ">="),
|
||||
Operator::StartsWith => write!(f, "starts-with"),
|
||||
Operator::EndsWith => write!(f, "ends-with"),
|
||||
Operator::Assignment(Assignment::Assign) => write!(f, "="),
|
||||
Operator::Comparison(Comparison::Equal) => write!(f, "=="),
|
||||
Operator::Comparison(Comparison::NotEqual) => write!(f, "!="),
|
||||
Operator::Comparison(Comparison::LessThan) => write!(f, "<"),
|
||||
Operator::Comparison(Comparison::GreaterThan) => write!(f, ">"),
|
||||
Operator::Comparison(Comparison::RegexMatch) => write!(f, "=~"),
|
||||
Operator::Comparison(Comparison::NotRegexMatch) => write!(f, "!~"),
|
||||
Operator::Comparison(Comparison::LessThanOrEqual) => write!(f, "<="),
|
||||
Operator::Comparison(Comparison::GreaterThanOrEqual) => write!(f, ">="),
|
||||
Operator::Comparison(Comparison::StartsWith) => write!(f, "starts-with"),
|
||||
Operator::Comparison(Comparison::EndsWith) => write!(f, "ends-with"),
|
||||
Operator::Comparison(Comparison::In) => write!(f, "in"),
|
||||
Operator::Comparison(Comparison::NotIn) => write!(f, "not-in"),
|
||||
Operator::Math(Math::Plus) => write!(f, "+"),
|
||||
Operator::Math(Math::Append) => write!(f, "++"),
|
||||
Operator::Math(Math::Minus) => write!(f, "-"),
|
||||
Operator::Math(Math::Multiply) => write!(f, "*"),
|
||||
Operator::Math(Math::Divide) => write!(f, "/"),
|
||||
Operator::Math(Math::Modulo) => write!(f, "mod"),
|
||||
Operator::Math(Math::FloorDivision) => write!(f, "fdiv"),
|
||||
Operator::Math(Math::Pow) => write!(f, "**"),
|
||||
Operator::Boolean(Boolean::And) => write!(f, "&&"),
|
||||
Operator::Boolean(Boolean::Or) => write!(f, "||"),
|
||||
Operator::Bits(Bits::BitOr) => write!(f, "bit-or"),
|
||||
Operator::Bits(Bits::BitXor) => write!(f, "bit-xor"),
|
||||
Operator::Bits(Bits::BitAnd) => write!(f, "bit-and"),
|
||||
Operator::Bits(Bits::ShiftLeft) => write!(f, "bit-shl"),
|
||||
Operator::Bits(Bits::ShiftRight) => write!(f, "bit-shr"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,11 +105,11 @@ impl EngineState {
|
||||
files: vec![],
|
||||
file_contents: vec![],
|
||||
vars: vec![
|
||||
Variable::new(Span::new(0, 0), Type::Any),
|
||||
Variable::new(Span::new(0, 0), Type::Any),
|
||||
Variable::new(Span::new(0, 0), Type::Any),
|
||||
Variable::new(Span::new(0, 0), Type::Any),
|
||||
Variable::new(Span::new(0, 0), Type::Any),
|
||||
Variable::new(Span::new(0, 0), Type::Any, false),
|
||||
Variable::new(Span::new(0, 0), Type::Any, false),
|
||||
Variable::new(Span::new(0, 0), Type::Any, false),
|
||||
Variable::new(Span::new(0, 0), Type::Any, false),
|
||||
Variable::new(Span::new(0, 0), Type::Any, false),
|
||||
],
|
||||
decls: vec![],
|
||||
aliases: vec![],
|
||||
@ -1571,7 +1571,13 @@ impl<'a> StateWorkingSet<'a> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn add_variable(&mut self, mut name: Vec<u8>, span: Span, ty: Type) -> VarId {
|
||||
pub fn add_variable(
|
||||
&mut self,
|
||||
mut name: Vec<u8>,
|
||||
span: Span,
|
||||
ty: Type,
|
||||
mutable: bool,
|
||||
) -> VarId {
|
||||
let next_id = self.next_var_id();
|
||||
|
||||
// correct name if necessary
|
||||
@ -1581,7 +1587,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||
|
||||
self.last_overlay_mut().vars.insert(name, next_id);
|
||||
|
||||
self.delta.vars.push(Variable::new(span, ty));
|
||||
self.delta.vars.push(Variable::new(span, ty, mutable));
|
||||
|
||||
next_id
|
||||
}
|
||||
@ -1643,6 +1649,15 @@ impl<'a> StateWorkingSet<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_variable_if_possible(&self, var_id: VarId) -> Option<&Variable> {
|
||||
let num_permanent_vars = self.permanent_state.num_vars();
|
||||
if var_id < num_permanent_vars {
|
||||
Some(self.permanent_state.get_var(var_id))
|
||||
} else {
|
||||
self.delta.vars.get(var_id - num_permanent_vars)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::borrowed_box)]
|
||||
pub fn get_decl(&self, decl_id: DeclId) -> &Box<dyn Command> {
|
||||
let num_permanent_decls = self.permanent_state.num_decls();
|
||||
|
@ -83,6 +83,24 @@ pub enum ShellError {
|
||||
#[diagnostic(code(nu::shell::unsupported_operator), url(docsrs))]
|
||||
UnsupportedOperator(Operator, #[label = "unsupported operator"] Span),
|
||||
|
||||
/// This value cannot be used with this operator.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Assignment requires that you assign to a variable or variable cell path.
|
||||
#[error("Assignment operations require a variable.")]
|
||||
#[diagnostic(code(nu::shell::assignment_requires_variable), url(docsrs))]
|
||||
AssignmentRequiresVar(#[label = "needs to be a variable"] Span),
|
||||
|
||||
/// This value cannot be used with this operator.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Assignment requires that you assign to a mutable variable or cell path.
|
||||
#[error("Assignment to an immutable variable.")]
|
||||
#[diagnostic(code(nu::shell::assignment_requires_mutable_variable), url(docsrs))]
|
||||
AssignmentRequiresMutableVar(#[label = "needs to be a mutable variable"] Span),
|
||||
|
||||
/// An operator was not recognized during evaluation.
|
||||
///
|
||||
/// ## Resolution
|
||||
|
@ -5,8 +5,8 @@ mod range;
|
||||
mod stream;
|
||||
mod unit;
|
||||
|
||||
use crate::ast::Operator;
|
||||
use crate::ast::{CellPath, PathMember};
|
||||
use crate::ast::{Bits, Boolean, CellPath, Comparison, PathMember};
|
||||
use crate::ast::{Math, Operator};
|
||||
use crate::ShellError;
|
||||
use crate::{did_you_mean, BlockId, Config, Span, Spanned, Type, VarId};
|
||||
use byte_unit::ByteUnit;
|
||||
@ -1734,7 +1734,7 @@ impl Value {
|
||||
}
|
||||
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Plus, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Plus), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
@ -1841,7 +1841,7 @@ impl Value {
|
||||
}
|
||||
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Minus, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Minus), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
@ -1927,7 +1927,7 @@ impl Value {
|
||||
})
|
||||
}
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Multiply, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Multiply), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
@ -2064,7 +2064,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Divide, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Divide), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
@ -2210,7 +2210,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Divide, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Divide), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
@ -2225,7 +2225,7 @@ impl Value {
|
||||
|
||||
pub fn lt(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
|
||||
return lhs.operation(*span, Operator::LessThan, op, rhs);
|
||||
return lhs.operation(*span, Operator::Comparison(Comparison::LessThan), op, rhs);
|
||||
}
|
||||
|
||||
if !type_compatible(self.get_type(), rhs.get_type())
|
||||
@ -2252,7 +2252,12 @@ impl Value {
|
||||
|
||||
pub fn lte(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
|
||||
return lhs.operation(*span, Operator::LessThanOrEqual, op, rhs);
|
||||
return lhs.operation(
|
||||
*span,
|
||||
Operator::Comparison(Comparison::LessThanOrEqual),
|
||||
op,
|
||||
rhs,
|
||||
);
|
||||
}
|
||||
|
||||
if !type_compatible(self.get_type(), rhs.get_type())
|
||||
@ -2279,7 +2284,12 @@ impl Value {
|
||||
|
||||
pub fn gt(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
|
||||
return lhs.operation(*span, Operator::GreaterThan, op, rhs);
|
||||
return lhs.operation(
|
||||
*span,
|
||||
Operator::Comparison(Comparison::GreaterThan),
|
||||
op,
|
||||
rhs,
|
||||
);
|
||||
}
|
||||
|
||||
if !type_compatible(self.get_type(), rhs.get_type())
|
||||
@ -2306,7 +2316,12 @@ impl Value {
|
||||
|
||||
pub fn gte(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
|
||||
return lhs.operation(*span, Operator::GreaterThanOrEqual, op, rhs);
|
||||
return lhs.operation(
|
||||
*span,
|
||||
Operator::Comparison(Comparison::GreaterThanOrEqual),
|
||||
op,
|
||||
rhs,
|
||||
);
|
||||
}
|
||||
|
||||
if !type_compatible(self.get_type(), rhs.get_type())
|
||||
@ -2333,7 +2348,7 @@ impl Value {
|
||||
|
||||
pub fn eq(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
|
||||
return lhs.operation(*span, Operator::Equal, op, rhs);
|
||||
return lhs.operation(*span, Operator::Comparison(Comparison::Equal), op, rhs);
|
||||
}
|
||||
|
||||
match self.partial_cmp(rhs) {
|
||||
@ -2358,7 +2373,7 @@ impl Value {
|
||||
|
||||
pub fn ne(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
|
||||
return lhs.operation(*span, Operator::NotEqual, op, rhs);
|
||||
return lhs.operation(*span, Operator::Comparison(Comparison::NotEqual), op, rhs);
|
||||
}
|
||||
|
||||
match self.partial_cmp(rhs) {
|
||||
@ -2426,7 +2441,7 @@ impl Value {
|
||||
})
|
||||
}
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::In, op, rhs)
|
||||
lhs.operation(*span, Operator::Comparison(Comparison::In), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2483,7 +2498,7 @@ impl Value {
|
||||
})
|
||||
}
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::NotIn, op, rhs)
|
||||
lhs.operation(*span, Operator::Comparison(Comparison::NotIn), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2528,9 +2543,9 @@ impl Value {
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => lhs.operation(
|
||||
*span,
|
||||
if invert {
|
||||
Operator::NotRegexMatch
|
||||
Operator::Comparison(Comparison::NotRegexMatch)
|
||||
} else {
|
||||
Operator::RegexMatch
|
||||
Operator::Comparison(Comparison::RegexMatch)
|
||||
},
|
||||
op,
|
||||
rhs,
|
||||
@ -2552,7 +2567,7 @@ impl Value {
|
||||
span,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::StartsWith, op, rhs)
|
||||
lhs.operation(*span, Operator::Comparison(Comparison::StartsWith), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2571,7 +2586,7 @@ impl Value {
|
||||
span,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::EndsWith, op, rhs)
|
||||
lhs.operation(*span, Operator::Comparison(Comparison::EndsWith), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2590,7 +2605,7 @@ impl Value {
|
||||
val: *lhs << rhs,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::ShiftLeft, op, rhs)
|
||||
lhs.operation(*span, Operator::Bits(Bits::ShiftLeft), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2609,7 +2624,7 @@ impl Value {
|
||||
val: *lhs >> rhs,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::ShiftRight, op, rhs)
|
||||
lhs.operation(*span, Operator::Bits(Bits::ShiftRight), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2628,7 +2643,7 @@ impl Value {
|
||||
val: *lhs | rhs,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::BitOr, op, rhs)
|
||||
lhs.operation(*span, Operator::Bits(Bits::BitOr), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2647,7 +2662,7 @@ impl Value {
|
||||
val: *lhs ^ rhs,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::BitXor, op, rhs)
|
||||
lhs.operation(*span, Operator::Bits(Bits::BitXor), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2666,7 +2681,7 @@ impl Value {
|
||||
val: *lhs & rhs,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::BitAnd, op, rhs)
|
||||
lhs.operation(*span, Operator::Bits(Bits::BitAnd), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2721,7 +2736,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Modulo, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Modulo), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
@ -2741,7 +2756,7 @@ impl Value {
|
||||
span,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::And, op, rhs)
|
||||
lhs.operation(*span, Operator::Boolean(Boolean::And), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2760,7 +2775,7 @@ impl Value {
|
||||
span,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Or, op, rhs)
|
||||
lhs.operation(*span, Operator::Boolean(Boolean::Or), op, rhs)
|
||||
}
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
@ -2797,7 +2812,7 @@ impl Value {
|
||||
span,
|
||||
}),
|
||||
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||
lhs.operation(*span, Operator::Pow, op, rhs)
|
||||
lhs.operation(*span, Operator::Math(Math::Pow), op, rhs)
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
|
@ -4,13 +4,15 @@ use crate::{Span, Type};
|
||||
pub struct Variable {
|
||||
pub declaration_span: Span,
|
||||
pub ty: Type,
|
||||
pub mutable: bool,
|
||||
}
|
||||
|
||||
impl Variable {
|
||||
pub fn new(declaration_span: Span, ty: Type) -> Variable {
|
||||
pub fn new(declaration_span: Span, ty: Type, mutable: bool) -> Variable {
|
||||
Self {
|
||||
declaration_span,
|
||||
ty,
|
||||
mutable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user