forked from extern/nushell
Add stepping to ranges & enable reverse ranges
Follows the following syntax: <start>..<next-value>..<end>
This commit is contained in:
parent
2d3a56f0d3
commit
4749776984
@ -85,13 +85,19 @@ pub fn eval_expression(
|
|||||||
val: *f,
|
val: *f,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
}),
|
}),
|
||||||
Expr::Range(from, to, operator) => {
|
Expr::Range(from, next, to, operator) => {
|
||||||
// TODO: Embed the min/max into Range and set max to be the true max
|
|
||||||
let from = if let Some(f) = from {
|
let from = if let Some(f) = from {
|
||||||
eval_expression(context, f)?
|
eval_expression(context, f)?
|
||||||
} else {
|
} else {
|
||||||
Value::Int {
|
Value::Nothing {
|
||||||
val: 0i64,
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let next = if let Some(s) = next {
|
||||||
|
eval_expression(context, s)?
|
||||||
|
} else {
|
||||||
|
Value::Nothing {
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -99,31 +105,13 @@ pub fn eval_expression(
|
|||||||
let to = if let Some(t) = to {
|
let to = if let Some(t) = to {
|
||||||
eval_expression(context, t)?
|
eval_expression(context, t)?
|
||||||
} else {
|
} else {
|
||||||
Value::Int {
|
Value::Nothing {
|
||||||
val: 100i64,
|
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let range = match (&from, &to) {
|
|
||||||
(&Value::Int { .. }, &Value::Int { .. }) => Range {
|
|
||||||
from: from.clone(),
|
|
||||||
to: to.clone(),
|
|
||||||
inclusion: operator.inclusion,
|
|
||||||
},
|
|
||||||
(lhs, rhs) => {
|
|
||||||
return Err(ShellError::OperatorMismatch {
|
|
||||||
op_span: operator.span,
|
|
||||||
lhs_ty: lhs.get_type(),
|
|
||||||
lhs_span: lhs.span(),
|
|
||||||
rhs_ty: rhs.get_type(),
|
|
||||||
rhs_span: rhs.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Value::Range {
|
Ok(Value::Range {
|
||||||
val: Box::new(range),
|
val: Box::new(Range::new(expr.span, from, next, to, operator)?),
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -159,7 +147,6 @@ pub fn eval_expression(
|
|||||||
x => Err(ShellError::UnsupportedOperator(x, op_span)),
|
x => Err(ShellError::UnsupportedOperator(x, op_span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Subexpression(block_id) => {
|
Expr::Subexpression(block_id) => {
|
||||||
let engine_state = context.engine_state.borrow();
|
let engine_state = context.engine_state.borrow();
|
||||||
let block = engine_state.get_block(*block_id);
|
let block = engine_state.get_block(*block_id);
|
||||||
|
@ -85,15 +85,19 @@ pub fn flatten_expression(
|
|||||||
}
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
Expr::Range(from, to, op) => {
|
Expr::Range(from, next, to, op) => {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
if let Some(f) = from {
|
if let Some(f) = from {
|
||||||
output.extend(flatten_expression(working_set, f));
|
output.extend(flatten_expression(working_set, f));
|
||||||
}
|
}
|
||||||
|
if let Some(s) = next {
|
||||||
|
output.extend(vec![(op.next_op_span, FlatShape::Operator)]);
|
||||||
|
output.extend(flatten_expression(working_set, s));
|
||||||
|
}
|
||||||
|
output.extend(vec![(op.span, FlatShape::Operator)]);
|
||||||
if let Some(t) = to {
|
if let Some(t) = to {
|
||||||
output.extend(flatten_expression(working_set, t));
|
output.extend(flatten_expression(working_set, t));
|
||||||
}
|
}
|
||||||
output.extend(vec![(op.span, FlatShape::Operator)]);
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
Expr::Bool(_) => {
|
Expr::Bool(_) => {
|
||||||
|
@ -709,8 +709,8 @@ pub fn parse_range(
|
|||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
// Range follows the following syntax: [<from>][<step_operator><step>]<range_operator>[<to>]
|
// Range follows the following syntax: [<from>][<next_operator><next>]<range_operator>[<to>]
|
||||||
// where <step_operator> is ".."
|
// where <next_operator> is ".."
|
||||||
// and <range_operator> is ".." or "..<"
|
// and <range_operator> is ".." or "..<"
|
||||||
// and one of the <from> or <to> bounds must be present (just '..' is not allowed since it
|
// and one of the <from> or <to> bounds must be present (just '..' is not allowed since it
|
||||||
// looks like parent directory)
|
// looks like parent directory)
|
||||||
@ -725,42 +725,28 @@ pub fn parse_range(
|
|||||||
// First, figure out what exact operators are used and determine their positions
|
// First, figure out what exact operators are used and determine their positions
|
||||||
let dotdot_pos: Vec<_> = token.match_indices("..").map(|(pos, _)| pos).collect();
|
let dotdot_pos: Vec<_> = token.match_indices("..").map(|(pos, _)| pos).collect();
|
||||||
|
|
||||||
let (step_op_pos, range_op_pos) =
|
let (next_op_pos, range_op_pos) =
|
||||||
match dotdot_pos.len() {
|
match dotdot_pos.len() {
|
||||||
1 => (None, dotdot_pos[0]),
|
1 => (None, dotdot_pos[0]),
|
||||||
2 => (Some(dotdot_pos[0]), dotdot_pos[1]),
|
2 => (Some(dotdot_pos[0]), dotdot_pos[1]),
|
||||||
_ => return (
|
_ => return (
|
||||||
garbage(span),
|
garbage(span),
|
||||||
Some(ParseError::Expected(
|
Some(ParseError::Expected(
|
||||||
"one range operator ('..' or '..<') and optionally one step operator ('..')"
|
"one range operator ('..' or '..<') and optionally one next operator ('..')"
|
||||||
.into(),
|
.into(),
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let _step_op_span = step_op_pos.map(|pos| {
|
let (inclusion, range_op_str, range_op_span) = if let Some(pos) = token.find("..<") {
|
||||||
Span::new(
|
|
||||||
span.start + pos,
|
|
||||||
span.start + pos + "..".len(), // Only ".." is allowed for step operator
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
let (range_op, range_op_str, range_op_span) = if let Some(pos) = token.find("..<") {
|
|
||||||
if pos == range_op_pos {
|
if pos == range_op_pos {
|
||||||
let op_str = "..<";
|
let op_str = "..<";
|
||||||
let op_span = Span::new(
|
let op_span = Span::new(
|
||||||
span.start + range_op_pos,
|
span.start + range_op_pos,
|
||||||
span.start + range_op_pos + op_str.len(),
|
span.start + range_op_pos + op_str.len(),
|
||||||
);
|
);
|
||||||
(
|
(RangeInclusion::RightExclusive, "..<", op_span)
|
||||||
RangeOperator {
|
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
|
||||||
span: op_span,
|
|
||||||
},
|
|
||||||
"..<",
|
|
||||||
op_span,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage(span),
|
garbage(span),
|
||||||
@ -776,21 +762,14 @@ pub fn parse_range(
|
|||||||
span.start + range_op_pos,
|
span.start + range_op_pos,
|
||||||
span.start + range_op_pos + op_str.len(),
|
span.start + range_op_pos + op_str.len(),
|
||||||
);
|
);
|
||||||
(
|
(RangeInclusion::Inclusive, "..", op_span)
|
||||||
RangeOperator {
|
|
||||||
inclusion: RangeInclusion::Inclusive,
|
|
||||||
span: op_span,
|
|
||||||
},
|
|
||||||
"..",
|
|
||||||
op_span,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Now, based on the operator positions, figure out where the bounds & step are located and
|
// Now, based on the operator positions, figure out where the bounds & next are located and
|
||||||
// parse them
|
// parse them
|
||||||
// TODO: Actually parse the step number
|
// TODO: Actually parse the next number
|
||||||
let from = if token.starts_with("..") {
|
let from = if token.starts_with("..") {
|
||||||
// token starts with either step operator, or range operator -- we don't care which one
|
// token starts with either next operator, or range operator -- we don't care which one
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let from_span = Span::new(span.start, span.start + dotdot_pos[0]);
|
let from_span = Span::new(span.start, span.start + dotdot_pos[0]);
|
||||||
@ -830,9 +809,32 @@ pub fn parse_range(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (next, next_op_span) = if let Some(pos) = next_op_pos {
|
||||||
|
let next_op_span = Span::new(span.start + pos, span.start + pos + "..".len());
|
||||||
|
let next_span = Span::new(next_op_span.end, range_op_span.start);
|
||||||
|
|
||||||
|
match parse_value(working_set, next_span, &SyntaxShape::Number) {
|
||||||
|
(expression, None) => (Some(Box::new(expression)), next_op_span),
|
||||||
|
_ => {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Expected("number".into(), span)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(None, Span::unknown())
|
||||||
|
};
|
||||||
|
|
||||||
|
let range_op = RangeOperator {
|
||||||
|
inclusion,
|
||||||
|
span: range_op_span,
|
||||||
|
next_op_span,
|
||||||
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(from, to, range_op),
|
expr: Expr::Range(from, next, to, range_op),
|
||||||
span,
|
span,
|
||||||
ty: Type::Range,
|
ty: Type::Range,
|
||||||
},
|
},
|
||||||
|
@ -164,6 +164,7 @@ mod range {
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
@ -195,6 +196,7 @@ mod range {
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
inclusion: RangeInclusion::RightExclusive,
|
||||||
@ -209,6 +211,38 @@ mod range {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_reverse_range() {
|
||||||
|
let engine_state = EngineState::new();
|
||||||
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
|
let (block, err) = parse(&mut working_set, None, b"10..0", true);
|
||||||
|
|
||||||
|
assert!(err.is_none());
|
||||||
|
assert!(block.len() == 1);
|
||||||
|
match &block[0] {
|
||||||
|
Statement::Pipeline(Pipeline { expressions }) => {
|
||||||
|
assert!(expressions.len() == 1);
|
||||||
|
assert!(matches!(
|
||||||
|
expressions[0],
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Range(
|
||||||
|
Some(_),
|
||||||
|
None,
|
||||||
|
Some(_),
|
||||||
|
RangeOperator {
|
||||||
|
inclusion: RangeInclusion::Inclusive,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => panic!("No match"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_subexpression_range() {
|
fn parse_subexpression_range() {
|
||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
@ -226,6 +260,7 @@ mod range {
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
inclusion: RangeInclusion::RightExclusive,
|
||||||
@ -257,6 +292,7 @@ mod range {
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
@ -288,6 +324,7 @@ mod range {
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
inclusion: RangeInclusion::RightExclusive,
|
||||||
@ -320,6 +357,7 @@ mod range {
|
|||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
..
|
||||||
@ -350,6 +388,7 @@ mod range {
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
|
@ -7,8 +7,9 @@ pub enum Expr {
|
|||||||
Int(i64),
|
Int(i64),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Range(
|
Range(
|
||||||
Option<Box<Expression>>,
|
Option<Box<Expression>>, // from
|
||||||
Option<Box<Expression>>,
|
Option<Box<Expression>>, // next value after "from"
|
||||||
|
Option<Box<Expression>>, // to
|
||||||
RangeOperator,
|
RangeOperator,
|
||||||
),
|
),
|
||||||
Var(VarId),
|
Var(VarId),
|
||||||
|
@ -59,6 +59,7 @@ pub enum RangeInclusion {
|
|||||||
pub struct RangeOperator {
|
pub struct RangeOperator {
|
||||||
pub inclusion: RangeInclusion,
|
pub inclusion: RangeInclusion,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub next_op_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for RangeOperator {
|
impl Display for RangeOperator {
|
||||||
|
@ -8,7 +8,7 @@ pub use stream::*;
|
|||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::ast::{PathMember, RangeInclusion};
|
use crate::ast::PathMember;
|
||||||
use crate::{span, BlockId, Span, Type};
|
use crate::{span, BlockId, Span, Type};
|
||||||
|
|
||||||
use crate::ShellError;
|
use crate::ShellError;
|
||||||
@ -131,20 +131,10 @@ impl Value {
|
|||||||
Value::Int { val, .. } => val.to_string(),
|
Value::Int { val, .. } => val.to_string(),
|
||||||
Value::Float { val, .. } => val.to_string(),
|
Value::Float { val, .. } => val.to_string(),
|
||||||
Value::Range { val, .. } => {
|
Value::Range { val, .. } => {
|
||||||
let vals: Vec<i64> = match (&val.from, &val.to) {
|
|
||||||
(Value::Int { val: from, .. }, Value::Int { val: to, .. }) => {
|
|
||||||
match val.inclusion {
|
|
||||||
RangeInclusion::Inclusive => (*from..=*to).collect(),
|
|
||||||
RangeInclusion::RightExclusive => (*from..*to).collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Vec::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"range: [{}]",
|
"range: [{}]",
|
||||||
vals.iter()
|
val.into_iter()
|
||||||
.map(|x| x.to_string())
|
.map(|x| x.into_string())
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
|
@ -1,12 +1,106 @@
|
|||||||
use crate::{ast::RangeInclusion, *};
|
use crate::{
|
||||||
|
ast::{RangeInclusion, RangeOperator},
|
||||||
|
*,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Range {
|
pub struct Range {
|
||||||
pub from: Value,
|
pub from: Value,
|
||||||
|
pub incr: Value,
|
||||||
pub to: Value,
|
pub to: Value,
|
||||||
pub inclusion: RangeInclusion,
|
pub inclusion: RangeInclusion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Range {
|
||||||
|
pub fn new(
|
||||||
|
expr_span: Span,
|
||||||
|
from: Value,
|
||||||
|
next: Value,
|
||||||
|
to: Value,
|
||||||
|
operator: &RangeOperator,
|
||||||
|
) -> Result<Range, ShellError> {
|
||||||
|
// Select from & to values if they're not specified
|
||||||
|
// TODO: Replace the placeholder values with proper min/max based on data type
|
||||||
|
let from = if let Value::Nothing { .. } = from {
|
||||||
|
Value::Int {
|
||||||
|
val: 0i64,
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
from
|
||||||
|
};
|
||||||
|
|
||||||
|
let to = if let Value::Nothing { .. } = to {
|
||||||
|
if let Ok(Value::Bool { val: true, .. }) = next.lt(expr_span, &from) {
|
||||||
|
Value::Int {
|
||||||
|
val: -100i64,
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Value::Int {
|
||||||
|
val: 100i64,
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
to
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the range counts up or down
|
||||||
|
let moves_up = matches!(from.lte(expr_span, &to), Ok(Value::Bool { val: true, .. }));
|
||||||
|
|
||||||
|
// Convert the next value into the inctement
|
||||||
|
let incr = if let Value::Nothing { .. } = next {
|
||||||
|
if moves_up {
|
||||||
|
Value::Int {
|
||||||
|
val: 1i64,
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Value::Int {
|
||||||
|
val: -1i64,
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next.sub(operator.next_op_span, &from)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let zero = Value::Int {
|
||||||
|
val: 0i64,
|
||||||
|
span: Span::unknown(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Increment must be non-zero, otherwise we iterate forever
|
||||||
|
if matches!(incr.eq(expr_span, &zero), Ok(Value::Bool { val: true, .. })) {
|
||||||
|
return Err(ShellError::CannotCreateRange(expr_span));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If to > from, then incr > 0, otherwise we iterate forever
|
||||||
|
if let (Value::Bool { val: true, .. }, Value::Bool { val: false, .. }) = (
|
||||||
|
to.gt(operator.span, &from)?,
|
||||||
|
incr.gt(operator.next_op_span, &zero)?,
|
||||||
|
) {
|
||||||
|
return Err(ShellError::CannotCreateRange(expr_span));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If to < from, then incr < 0, otherwise we iterate forever
|
||||||
|
if let (Value::Bool { val: true, .. }, Value::Bool { val: false, .. }) = (
|
||||||
|
to.lt(operator.span, &from)?,
|
||||||
|
incr.lt(operator.next_op_span, &zero)?,
|
||||||
|
) {
|
||||||
|
return Err(ShellError::CannotCreateRange(expr_span));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Range {
|
||||||
|
from,
|
||||||
|
incr,
|
||||||
|
to,
|
||||||
|
inclusion: operator.inclusion,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IntoIterator for Range {
|
impl IntoIterator for Range {
|
||||||
type Item = Value;
|
type Item = Value;
|
||||||
|
|
||||||
@ -25,8 +119,7 @@ pub struct RangeIterator {
|
|||||||
span: Span,
|
span: Span,
|
||||||
is_end_inclusive: bool,
|
is_end_inclusive: bool,
|
||||||
moves_up: bool,
|
moves_up: bool,
|
||||||
one: Value,
|
incr: Value,
|
||||||
negative_one: Value,
|
|
||||||
done: bool,
|
done: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,8 +145,7 @@ impl RangeIterator {
|
|||||||
span,
|
span,
|
||||||
is_end_inclusive: matches!(range.inclusion, RangeInclusion::Inclusive),
|
is_end_inclusive: matches!(range.inclusion, RangeInclusion::Inclusive),
|
||||||
done: false,
|
done: false,
|
||||||
one: Value::Int { val: 1, span },
|
incr: range.incr,
|
||||||
negative_one: Value::Int { val: -1, span },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,10 +162,10 @@ impl Iterator for RangeIterator {
|
|||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else {
|
} else {
|
||||||
match (&self.curr, &self.end) {
|
match (&self.curr, &self.end) {
|
||||||
(Value::Int { val: x, .. }, Value::Int { val: y, .. }) => x.cmp(y),
|
(Value::Int { val: curr, .. }, Value::Int { val: end, .. }) => curr.cmp(end),
|
||||||
// (Value::Float { val: x, .. }, Value::Float { val: y, .. }) => x.cmp(y),
|
// (Value::Float { val: curr, .. }, Value::Float { val: end, .. }) => curr.cmp(end),
|
||||||
// (Value::Float { val: x, .. }, Value::Int { val: y, .. }) => x.cmp(y),
|
// (Value::Float { val: curr, .. }, Value::Int { val: end, .. }) => curr.cmp(end),
|
||||||
// (Value::Int { val: x, .. }, Value::Float { val: y, .. }) => x.cmp(y),
|
// (Value::Int { val: curr, .. }, Value::Float { val: end, .. }) => curr.cmp(end),
|
||||||
_ => {
|
_ => {
|
||||||
self.done = true;
|
self.done = true;
|
||||||
return Some(Value::Error {
|
return Some(Value::Error {
|
||||||
@ -83,10 +175,15 @@ impl Iterator for RangeIterator {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.moves_up
|
let desired_ordering = if self.moves_up {
|
||||||
&& (ordering == Ordering::Less || self.is_end_inclusive && ordering == Ordering::Equal)
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Greater
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ordering == desired_ordering) || (self.is_end_inclusive && ordering == Ordering::Equal)
|
||||||
{
|
{
|
||||||
let next_value = self.curr.add(self.span, &self.one);
|
let next_value = self.curr.add(self.span, &self.incr);
|
||||||
|
|
||||||
let mut next = match next_value {
|
let mut next = match next_value {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
@ -98,22 +195,6 @@ impl Iterator for RangeIterator {
|
|||||||
};
|
};
|
||||||
std::mem::swap(&mut self.curr, &mut next);
|
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)
|
Some(next)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
Loading…
Reference in New Issue
Block a user